网盘直链解析

支持批量获取 ✅百度网盘 ✅阿里云盘 ✅天翼云盘 ✅迅雷云盘 ✅夸克网盘 ✅移动云盘 六大网盘的直链下载地址,配合 IDM,Xdown,Aria2,Curl,比特彗星等工具高效🚀🚀🚀下载,完美适配 Chrome,Edge,FireFox,360,QQ,搜狗,百分,遨游,星愿,Opera,猎豹,Vivaldi,Yandex,Kiwi 等 18 种浏览器。可在无法安装客户端的环境下使用,助手免费开源。😎

  1. // ==UserScript==
  2. // @name 网盘直链解析
  3. // @namespace wpjx
  4. // @version 1.1.1
  5. // @author GreasyForksOrXnyjj
  6. // @description 支持批量获取 ✅百度网盘 ✅阿里云盘 ✅天翼云盘 ✅迅雷云盘 ✅夸克网盘 ✅移动云盘 六大网盘的直链下载地址,配合 IDM,Xdown,Aria2,Curl,比特彗星等工具高效🚀🚀🚀下载,完美适配 Chrome,Edge,FireFox,360,QQ,搜狗,百分,遨游,星愿,Opera,猎豹,Vivaldi,Yandex,Kiwi 等 18 种浏览器。可在无法安装客户端的环境下使用,助手免费开源。😎
  7. // @license AGPL-3.0-or-later
  8. // @homepage https://www.youxiaohou.com/install.html
  9. // @supportURL https://github.com/syhyz1990/baiduyun
  10. // @antifeature membership
  11. // @match *://pan.baidu.com/disk/home*
  12. // @match *://yun.baidu.com/disk/home*
  13. // @match *://pan.baidu.com/disk/main*
  14. // @match *://yun.baidu.com/disk/main*
  15. // @match *://pan.baidu.com/s/*
  16. // @match *://yun.baidu.com/s/*
  17. // @match *://*/*
  18. // @match *://pan.baidu.com/share/*
  19. // @match *://yun.baidu.com/share/*
  20. // @match *://www.aliyundrive.com/s/*
  21. // @match *://www.aliyundrive.com/drive*
  22. // @match *://www.alipan.com/s/*
  23. // @match *://www.alipan.com/drive*
  24. // @match *://cloud.189.cn/web/*
  25. // @match *://pan.xunlei.com/*
  26. // @match *://pan.quark.cn/*
  27. // @match *://yun.139.com/*
  28. // @match *://caiyun.139.com/*
  29. // @require https://registry.npmmirror.com/jquery/3.7.0/files/dist/jquery.min.js
  30. // @require https://registry.npmmirror.com/sweetalert2/10.16.6/files/dist/sweetalert2.all.min.js
  31. // @require https://registry.npmmirror.com/js-md5/0.7.3/files/build/md5.min.js
  32. // @connect baidu.com
  33. // @connect baidupcs.com
  34. // @connect aliyundrive.com
  35. // @connect alipan.com
  36. // @connect 189.cn
  37. // @connect xunlei.com
  38. // @connect quark.cn
  39. // @connect youxiaohou.com
  40. // @connect yun.139.com
  41. // @connect caiyun.139.com
  42. // @connect 124.222.202.139
  43. // @connect localhost
  44. // @connect *
  45. // @run-at document-idle
  46. // @grant unsafeWindow
  47. // @grant GM_xmlhttpRequest
  48. // @grant GM_setClipboard
  49. // @grant GM_setValue
  50. // @grant GM_getValue
  51. // @grant GM_openInTab
  52. // @grant GM_info
  53. // @grant GM_registerMenuCommand
  54. // @grant GM_cookie
  55. // @grant GM_getResourceText
  56. // @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48cGF0aCBkPSJNMTAzLjYgMTA3LjRjMy41LTIuMiA4LjktNi4xIDEzLjgtMTIuNXM3LjMtMTIuNSA4LjUtMTYuNWMuNS0xLjcgMi4yLTcuNSAyLjItMTQuNyAwLTEwLjEtMy4zLTI1LjEtMTUuNC0zNi44LTE0LjUtMTQtMzIuMS0xNC4zLTM1LjctMTQuMy04IDAtMTUuNyAxLjktMjIuNiA1LjJDNDQgMjMgMzUuNyAzMS40IDMwLjggNDEuN2MtMS4zIDIuOC00IDQuNy03LjEgNS00IC4zLTcuNSA0LjQtOC45IDkuNi0uNSAxLjktMS42IDMuNS0zLjEgNC43QzQuNCA2Ni44IDAgNzUuNyAwIDg1YzAgNi44IDIuMyAxMy4xIDYuMSAxOC4yIDUuNSA3LjQgMTQuMiAxMi4yIDI0IDEyLjJoNDcuMWM0LjQgMCAxMS0uNSAxOC4zLTMuNSAzLjItMS40IDUuOS0zIDguMS00LjV6IiBmaWxsPSIjNDQ0Ii8+PHBhdGggZD0iTTExOS44IDY0LjNjLjEtMTcuMS0xMC40LTI4LTEyLjUtMzAuMUM5NSAyMi4xIDc5LjkgMjEuOCA3Ni45IDIxLjhjLTE3LjYgMC0zMy4zIDEwLjUtMzkuOSAyNi43LS42IDEuMy0xLjggMi4zLTMuNCAyLjNoLS40Yy01LjggMC0xMC42IDQuOC0xMC42IDEwLjd2LjVjMCAxLjQtLjggMi42LTEuOSAzLjNDMTMuNCA2OSA4LjggNzYuOCA4LjggODVjMCAxMi4yIDkuOSAyMi4zIDIyLjIgMjIuM2g0NS4yYzMuNi0uMSAxNy42LS45IDI5LjYtMTIgMi45LTIuOCAxMy45LTEzLjcgMTQtMzF6IiBmaWxsPSIjMTM5N2Q4Ii8+PHBhdGggZD0iTTExMC44IDU3LjRsLjIgMy4zYzAgMS4zLTEuMSAyLjQtMi4zIDIuNC0xLjMgMC0yLjMtMS4xLTIuMy0yLjRsLS4xLTIuOHYtLjNjMC0xLjIuOS0yLjIgMi4xLTIuM2guM2MuNyAwIDEuMy4zIDEuNy43LS4yLjEuMy41LjQgMS40em0tMy4zLTEwLjNjMCAxLjItMSAyLjMtMi4yIDIuM2gtLjFjLS44IDAtMS42LS41LTItMS4yLTQuNi04LjMtMTMuMy0xMy41LTIyLjgtMTMuNS0xLjIgMC0yLjMtMS0yLjMtMi4ydi0uMWMwLTEuMiAxLTIuMyAyLjItMi4zaC4xYTMwLjM3IDMwLjM3IDAgMCAxIDE1LjggNC40YzQuNiAyLjggOC40IDYuOCAxMS4xIDExLjUuMS4zLjIuNy4yIDEuMXpNODguMyA3My44TDczLjUgOTMuMmMtMS41IDEuOS0zLjUgMy4xLTUuNyAzLjVoLS4yYy0uNC4xLS44LjEtMS4yLjEtLjYgMC0xLjEtLjEtMS42LS4yLTIuMi0uNC00LjItMS43LTUuNi0zLjVMNDQuMyA3My45Yy0yLTIuNi0yLjUtNS40LTEuNC03LjcuMS0uMS4xLS4yLjItLjIgMS4yLTIgMy41LTMuMiA2LjQtMy4yaDYuNnYtNS43YzAtNi44IDQuNy0xMiAxMC45LTEyIDQuOCAwIDguNSAyLjYgMTAuMyA3LjIuNSAxLjMtLjIgMi43LTEuNSAzLjJzLTIuOC0uMS0zLjMtMS40Yy0xLjEtMi43LTIuOS00LTUuNS00LTMuNSAwLTYgMy02IDd2OC4xYzAgLjUtLjIgMS0uNiAxLjQtLjYuNy0xLjcgMS4xLTIuNiAxLjFoLTguNGMtMS4zIDAtMiAuNC0yLjEuNy0uMi40IDAgMS4zLjkgMi40TDYzLjEgOTBjLjkgMS4yIDIuMSAxLjggMy4zIDEuOHMyLjMtLjYgMy4xLTEuN2wxNC44LTE5LjNjLjktMS4xIDEuMS0yIC45LTIuNC0uMi0uMy0uOS0uNy0yLjEtLjdoLTcuNmMtLjkgMC0xLjctLjUtMi4xLTEuMi0uMy0uNC0uNC0uOC0uNC0xLjMgMC0xLjQgMS4xLTIuNSAyLjUtMi41aDcuNmMzLjEgMCA1LjUgMS4zIDYuNiAzLjVsLjMuN2MuNyAyLjEuMSA0LjYtMS43IDYuOXoiIGZpbGw9IiM0NDQiLz48L3N2Zz4=
  57. // ==/UserScript==
  58.  
  59. (function () {
  60. 'use strict';
  61.  
  62. // 界面参数
  63. let splName =10,timer=null, pt = '',dataRow=[],searchList=[],searchTempList=[], searchKey=0,selectList = [], params = {}, mode = '', width = '', pan = {}, color = '',
  64. update = '', update_baidu = '', update_baiduX = '',
  65. doc = $(document), progress = {}, request = {}, ins = {}, idm = {};
  66.  
  67.  
  68.  
  69. // 准备好对应的元素
  70. let customClass = {
  71. popup: 'pl-popup',
  72. header: 'pl-header',
  73. title: 'pl-title',
  74. closeButton: 'pl-close',
  75. content: 'pl-content',
  76. input: 'pl-input',
  77. footer: 'pl-footer'
  78. };
  79.  
  80.  
  81. // 准备好Shell类型(用于curl下载)
  82. let terminalType = {
  83. wc: "Microsoft Windows 命令提示符",
  84. wp: "Microsoft Windows PowerShell",
  85. lt: "Linux 终端",
  86. ls: "Linux Shell",
  87. mt: "Apple MacOS 终端",
  88. };
  89.  
  90. //准备好信息界面的设置选项
  91. let updatecheck = {
  92. yes: "自动检查更新",
  93. no: "不检查更新"
  94. }
  95. let youserver = {
  96. v1: "使用 [用油小猴服务器 V1 接口]",
  97. v2: "使用 [用油小猴服务器 V2 接口]",
  98. no: "不使用 [用 jsdelivr 连接本项目 Github 仓库](更新可能不及时)"
  99. };
  100. let baidutheme = {
  101. yes: "修改主题色",
  102. no: "不修改主题色"
  103. };
  104.  
  105. //准备好右上角的Toast提示
  106. let toast = Swal.mixin({
  107. toast: true,
  108. position: 'top-end',
  109. showConfirmButton: false,
  110. timer: 3500,
  111. timerProgressBar: true,
  112. showCloseButton: true,
  113. didOpen: (toast) => {
  114. toast.addEventListener('mouseenter', Swal.stopTimer);
  115. toast.addEventListener('mouseleave', Swal.resumeTimer);
  116. }
  117. });
  118.  
  119. //提示的信息内容
  120. let message = {
  121. success: (text) => {
  122. toast.fire({title: text, icon: 'success'});
  123. },
  124. error: (text) => {
  125. toast.fire({title: text, icon: 'error'});
  126. },
  127. warning: (text) => {
  128. toast.fire({title: text, icon: 'warning'});
  129. },
  130. info: (text) => {
  131. toast.fire({title: text, icon: 'info'});
  132. },
  133. question: (text) => {
  134. toast.fire({title: text, icon: 'question'});
  135. }
  136. };
  137.  
  138. // 封装好要用的函数
  139. let base = {
  140. panData:[],
  141. panTemp:[],
  142. panList:[],
  143. panKey:0,
  144. // 默认菜单
  145. registerMenuCommand() {
  146. GM_registerMenuCommand('⚙️ 设置', () => {
  147. base.showSetting();
  148. });
  149. GM_registerMenuCommand('📃 更新', () => {
  150. base.showUpdateLog();
  151. });
  152. GM_registerMenuCommand('🛠️ 调试', () => {
  153. base.showInfo();
  154. });
  155. },
  156.  
  157. // 对于非网盘的菜单
  158. registerPanMenuCommand() {
  159. GM_registerMenuCommand('⚙️ 设置', () => {
  160. base.showSetting();
  161. });
  162. GM_registerMenuCommand('📃 更新', () => {
  163. base.showUpdateLog();
  164. });
  165. GM_registerMenuCommand('🛠️ 调试', () => {
  166. base.showPanInfo();
  167. });
  168. },
  169.  
  170. // 取消点亮按钮按下后运行的
  171. registerInitCode(value) {
  172. console.log("【网盘下载助手】\n正在注入取消点亮按钮设置项目...");
  173. message.warning("正在注入取消点亮按钮设置项目...(您可以再次点亮按钮)");
  174. base.setValue('setting_init_code', value);
  175. base.setValue('license', null);
  176. history.go(0)
  177. },
  178.  
  179.  
  180. // 获取Cookie
  181. getCookie(name) {
  182. let cookies = document.cookie.split(';');
  183. for (let i = 0; i < cookies.length; i++) {
  184. let cookiePair = cookies[i].trim().split('=');
  185. if (cookiePair.length === 2) {
  186. let cookieName = cookiePair[0];
  187. if (cookieName === name) {
  188. return cookiePair[1];
  189. }
  190. }
  191. }
  192. return '';
  193. },
  194.  
  195.  
  196. /*-- 对象类型判断
  197. 示例:
  198. isType([]) // 输出"array"
  199. isType(123) // 输出"number"
  200. isType(null) // 输出"null"
  201. isType(new Date()) // 输出"date"
  202. */
  203. isType(obj) {
  204. return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
  205. },
  206.  
  207.  
  208. // 获取本地保存的数值(仅用于 Greasemonkey)
  209. getValue(name) {
  210. return GM_getValue(name);
  211. },
  212.  
  213. // 修改本地保存的数值(仅用于 Greasemonkey)
  214. setValue(name, value) {
  215. GM_setValue(name, value);
  216. },
  217.  
  218. // 获取本地保存的数值
  219. getStorage(key) {
  220. try {
  221. return JSON.parse(localStorage.getItem(key));
  222. } catch (e) {
  223. return localStorage.getItem(key);
  224. }
  225. },
  226.  
  227. // 修改本地保存的数值
  228. setStorage(key, value) {
  229. if (this.isType(value) === 'object' || this.isType(value) === 'array') {
  230. return localStorage.setItem(key, JSON.stringify(value));
  231. }
  232. return localStorage.setItem(key, value);
  233. },
  234.  
  235. // 设置剪贴板(仅用于 Greasemonkey)
  236. setClipboard(text) {
  237. GM_setClipboard(text, 'text');
  238. },
  239.  
  240. // 加密成base64(先转换成URL编码)
  241. encode(str) {
  242. return btoa(unescape(encodeURIComponent(str)));
  243. },
  244.  
  245. // 从base64解密
  246. decode(str) {
  247. return decodeURIComponent(escape(atob(str)));
  248. },
  249.  
  250. //数字补零
  251. repairTimer(i){
  252. if (i >= 0 && i <= 9) {
  253. return "0" + i;
  254. } else {
  255. return i;
  256. }
  257. },
  258.  
  259. // 接受文件名并返回大写扩展名
  260. getExtension(name) {
  261. const reg = /(?!\.)\w+$/;
  262. if (reg.test(name)) {
  263. let match = name.match(reg);
  264. return match[0].toUpperCase();
  265. }
  266. return '';
  267. },
  268.  
  269. // 文件大小转换(以字节为单位)
  270. sizeFormat(value) {
  271. if (value === +value) {
  272. let unit = ["字节(B)", "千字节(KB)", "兆字节(MB)", "吉字节(GB)", "太字节(TB)", "拍字节(PB)", "艾字节(EB)", "泽字节(ZB)", "尧字节(YB)"];
  273. if (value === 0) {
  274. return "0字节(B)";
  275. } else {
  276. let index = Math.floor(Math.log(value) / Math.log(1024));
  277. let size = value / Math.pow(1024, index);
  278. size = size.toFixed(1);
  279. return size + unit[index];
  280. }
  281. }
  282. return '';
  283. },
  284.  
  285. // 根据数组中的每个文件名进行排序,使用了localeCompare方法来比较中文字符串的顺序。
  286. sortByName(arr) {
  287. const handle = () => {
  288. return (a, b) => {
  289. const p1 = a.filename ? a.filename : a.server_filename;
  290. const p2 = b.filename ? b.filename : b.server_filename;
  291. return p1.localeCompare(p2, "zh-CN");
  292. };
  293. };
  294. arr.sort(handle());
  295. },
  296.  
  297. // 替换特殊字符为下划线
  298. fixFilename(name) {
  299. let replace = /[!?&|`"'*\/:<>\\]/g
  300. return name.replace(replace, '_');
  301. },
  302.  
  303. // 接受Blob对象和文件名,然后创建临时链接指向blob对象,之后创建a标签指向临时链接和设置文件名,最后模拟点击a标签实现下载和释放临时链接
  304. blobDownload(blob, filename) {
  305. if (blob instanceof Blob) {
  306. const url = URL.createObjectURL(blob);
  307. const a = document.createElement('a');
  308. a.href = url;
  309. a.download = filename;
  310. a.click();
  311. URL.revokeObjectURL(url);
  312. }
  313. },
  314.  
  315. // 使用Post发送请求
  316. post(url, data, headers, type, maxRetries = 10, currentRetry = 0) {
  317. if (this.isType(data) === 'object') {
  318. data = JSON.stringify(data);
  319. }
  320. return new Promise((resolve, reject) => {
  321. const sendRequest = () => {
  322. GM_xmlhttpRequest({
  323. method: "POST", url, headers, data,
  324. responseType: type || 'json',
  325. onload: (res) => {
  326. if (/^[A-Za-z0-9+/=\s]+$/.test(res.response) && /^[A-Za-z0-9+/=\s]+$/.test(res.responseText)) {
  327. if (res.response) {
  328. res.decodedResponse = JSON.parse(base.decode(res.response));
  329. }
  330. if (res.responseText) {
  331. res.decodedResponseText = base.decode(res.responseText);
  332. }
  333. }
  334. console.log('【网盘下载助手】Post\n请求地址:' + url + '\n请求头部:' + JSON.stringify(headers) + '\n请求结果:', res);
  335. type === 'blob' ? resolve(res) : resolve(res.response || res.responseText);
  336. },
  337. onerror: (err) => {
  338. if (currentRetry < maxRetries) {
  339. currentRetry++;
  340. console.error(`【网盘下载助手】Post\n请求出现错误,可能是网络问题\n5秒后将重试 (错误次数:${currentRetry}/${maxRetries})...`, err);
  341. setTimeout(function(){
  342. console.log(`【网盘下载助手】Post\n重新尝试请求...`);
  343. sendRequest(); // 重新发送请求
  344. },5000)
  345. } else {
  346. reject('【网盘下载助手】Post\n请求出现错误,可能是网络问题\n无法继续请求,达到最大错误次数。', err); // 达到最大重试次数,拒绝 Promise
  347. }
  348. },
  349. });
  350. };
  351. sendRequest(); // 初始请求
  352. });
  353. },
  354.  
  355. // 使用Get发送请求
  356. get(url, headers, type, extra, maxRetries = 10, currentRetry = 0) {
  357. return new Promise((resolve, reject) => {
  358. const sendRequest = () => {
  359. let requestObj = GM_xmlhttpRequest({
  360. method: "GET", url, headers,
  361. responseType: type || 'json',
  362. onload: (res) => {
  363. if (res.status === 204) {
  364. requestObj.abort();
  365. idm[extra.index] = true;
  366. }
  367. if (type === 'blob') {
  368. res.status === 200 && base.blobDownload(res.response, extra.filename);
  369. resolve(res);
  370. } else {
  371. resolve(res.response || res.responseText);
  372. }
  373. },
  374. onprogress: (res) => {
  375. if (extra && extra.filename && extra.index) {
  376. res.total > 0 ? progress[extra.index] = (res.loaded * 100 / res.total).toFixed(2) : progress[extra.index] = 0.00;
  377. }
  378. },
  379. onloadstart() {
  380. extra && extra.filename && extra.index && (request[extra.index] = requestObj);
  381. },
  382. onerror: (err) => {
  383. if (currentRetry < maxRetries) {
  384. currentRetry++;
  385. console.error(`【网盘下载助手】Get\n请求出现错误,可能是网络问题\n5秒后将重试 (错误次数:${currentRetry}/${maxRetries})...`, err);
  386. setTimeout(function(){
  387. console.log(`【网盘下载助手】Get\n重新尝试请求...`);
  388. sendRequest(); // 重新发送请求
  389. },5000)
  390. } else {
  391. reject('【网盘下载助手】Get\n请求出现错误,可能是网络问题\n无法继续请求,达到最大错误次数。', err); // 达到最大重试次数,拒绝 Promise
  392. }
  393. },
  394. });
  395. };
  396.  
  397. sendRequest(); // 初始请求
  398. });
  399. },
  400.  
  401. // 获取最终链接
  402. getFinalUrl(url, headers, maxRetries = 10, currentRetry = 0) {
  403. return new Promise((resolve, reject) => {
  404. const sendRequest = () => {
  405. let requestObj = GM_xmlhttpRequest({
  406. method: "GET", url, headers,
  407. onload: (res) => {
  408. console.log('【网盘下载助手】Get FinalUrl\n请求地址:' + url + '\n请求头部:' + JSON.stringify(headers) + '\n返回结果:', res);
  409. resolve(res.finalUrl);
  410. },
  411. onerror: (err) => {
  412. if (currentRetry < maxRetries) {
  413. currentRetry++;
  414. console.error(`【网盘下载助手】Get FinalUrl\n请求出现错误,可能是网络问题\n5秒后将重试 (错误次数:${currentRetry}/${maxRetries})...`);
  415. setTimeout(function(){
  416. console.log(`【网盘下载助手】Get FinalUrl\n重新尝试请求...`);
  417. sendRequest(); // 重新发送请求
  418. },5000)
  419. } else {
  420. reject('【网盘下载助手】Get FinalUrl\n请求出现错误,可能是网络问题\n无法继续请求,达到最大错误次数。', err); // 达到最大重试次数,拒绝 Promise
  421. }
  422. },
  423. });
  424. };
  425.  
  426. sendRequest(); // 初始请求
  427. });
  428. },
  429.  
  430. // 获取脚本信息
  431. fetchScriptInfo(url, retryCount) {
  432. return fetch(url)
  433. .then(response => response.json())
  434. .then(data => {
  435. console.log('【网盘下载助手】Fetch\n请求地址:' + url + ' (GreasyFork)\n返回结果:', data);
  436. return data;
  437. })
  438. .catch(error => {
  439. console.error('【网盘下载助手】Fetch\n获取脚本版本时发生错误', error);
  440. if (retryCount > 0) {
  441. console.log("【网盘下载助手】Fetch\n5秒后将重新尝试获取版本");
  442. return new Promise(resolve => setTimeout(resolve, 5000))
  443. .then(() => {
  444. console.log('【网盘下载助手】Fetch\n重新尝试获取脚本信息...');
  445. return fetchScriptInfo(url, retryCount - 1);
  446. });
  447. } else {
  448. console.error('【网盘下载助手】Fetch\n请求出现错误,可能是网络问题\n无法获取脚本信息,达到最大尝试次数。');
  449. throw error;
  450. }
  451. });
  452. },
  453.  
  454. // RPC测试
  455. async rpcTest(domain, port, path, token) {
  456. return new Promise((resolve, reject) => {
  457. let rpc = { domain, port, path, token };
  458. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  459. let rpcData = {
  460. id: new Date().getTime(),
  461. jsonrpc: '2.0',
  462. method: 'system.listMethods',
  463. params: [`token:${rpc.token}`],
  464. };
  465. GM_xmlhttpRequest({
  466. method: "POST", url, headers: {}, data: JSON.stringify(rpcData),
  467. responseType: 'json',
  468. onload: (res) => {
  469. console.log('【网盘下载助手】Post RPCTest\n请求地址:' + url + '\n请求结果:', res);
  470. if(res.response){
  471. resolve("success");
  472. } else {
  473. resolve("fail");
  474. }
  475. },
  476. onerror: (err) => {
  477. console.error('【网盘下载助手】Post RPCTest\n请求失败', err);
  478. resolve("fail");
  479. },
  480. });
  481. });
  482. },
  483.  
  484. stringify(obj) {
  485. let str = '';
  486. for (var key in obj) {
  487. if (obj.hasOwnProperty(key)) {
  488. var value = obj[key];
  489. if (Array.isArray(value)) {
  490. for (var i = 0; i < value.length; i++) {
  491. str += encodeURIComponent(key) + '=' + encodeURIComponent(value[i]) + '&';
  492. }
  493. } else {
  494. str += encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
  495. }
  496. }
  497. }
  498. return str.slice(0, -1); // 去掉末尾的 "&"
  499. },
  500.  
  501. addStyle(id, tag, css) {
  502. tag = tag || 'style';
  503. let doc = document, styleDom = doc.getElementById(id);
  504. if (styleDom) styleDom.remove();
  505. let style = doc.createElement(tag);
  506. style.rel = 'stylesheet';
  507. style.id = id;
  508. tag === 'style' ? style.innerHTML = css : style.href = css;
  509. doc.getElementsByTagName('body')[0].appendChild(style);
  510. },
  511.  
  512. sleep(time) {
  513. return new Promise(resolve => setTimeout(resolve, time));
  514. },
  515.  
  516. findReact(dom, traverseUp = 0) {
  517. const key = Object.keys(dom).find(key => {
  518. return key.startsWith("__reactFiber$")
  519. || key.startsWith("__reactInternalInstance$");
  520. });
  521. const domFiber = dom[key];
  522. if (domFiber == null) return null;
  523.  
  524. if (domFiber._currentElement) {
  525. let compFiber = domFiber._currentElement._owner;
  526. for (let i = 0; i < traverseUp; i++) {
  527. compFiber = compFiber._currentElement._owner;
  528. }
  529. return compFiber._instance;
  530. }
  531.  
  532. const GetCompFiber = fiber => {
  533. let parentFiber = fiber.return;
  534. while (typeof parentFiber.type == "string") {
  535. parentFiber = parentFiber.return;
  536. }
  537. return parentFiber;
  538. };
  539. let compFiber = GetCompFiber(domFiber);
  540. for (let i = 0; i < traverseUp; i++) {
  541. compFiber = GetCompFiber(compFiber);
  542. }
  543. return compFiber.stateNode || compFiber;
  544. },
  545.  
  546. //注册(不可用)默认设置
  547. initDefaultConfig() {
  548. let value = [{
  549. name: 'setting_rpc_domain',
  550. value: 'http://localhost'
  551. }, {
  552. name: 'setting_rpc_port',
  553. value: '16800'
  554. }, {
  555. name: 'setting_rpc_path',
  556. value: '/jsonrpc'
  557. }, {
  558. name: 'setting_rpc_token',
  559. value: ''
  560. }, {
  561. name: 'setting_rpc_dir',
  562. value: 'D:\Downloads'
  563. }, {
  564. name: 'setting_terminal_type',
  565. value: 'wc'
  566. }, {
  567. name: 'setting_theme_color',
  568. value: '#574AB8'
  569. }, {
  570. name: 'setting_init_code',
  571. value: ''
  572. }, {
  573. name: 'license',
  574. value: ''
  575. }, {
  576. name: 'setting_youxiaohou_server',
  577. value: 'v2'
  578. }, {
  579. name: 'setting_baidu_theme',
  580. value: 'no'
  581. }];
  582.  
  583. value.forEach((v) => {
  584. // 没有对应的项目就添加上项目
  585. base.getValue(v.name) === undefined && base.setValue(v.name, v.value);
  586. });
  587. },
  588.  
  589. // 设置界面
  590. showSetting() {
  591. let dom = '',
  592. btn = '',
  593. colorList = ['#09AAFF','#cc3235','#637df8','#518c17','#ed944b','#f969a5','#bca280','#574AB8','#0d53ff','#637dff','#3181f9','#f8d800','#0396ff','#32ccbc','#f6416c','#2271b1','#59524c','#10171d','#1d2327','#18a497'],
  594. colorNameList = ['度盘<br>经典蓝','度盘<br>平安红','度盘<br>霞光紫','度盘<br>盎然绿','度盘<br>周年橙','度盘<br>幸会粉','度盘<br>午后棕','度盘<br>星空紫','夸克<br>明亮蓝','阿里<br>云盘紫','移动<br>彩云蓝','果核<br>柠檬黄','果核<br>默认蓝','果核<br>碧波绿','果核<br>玫瑰红','文派<br>默认蓝','文派<br>咖啡灰','文派<br>默认黑','OpenAI<br>默认黑','OpenAI<br>默认青'];
  595. dom += `<label class="pl-setting-label"><div class="pl-label">RPC主机</div><input type="text" placeholder="主机地址,需带上http(s)://,但不需要写端口与路径" class="swal2-input pl-input listener-domain" value="${base.getValue('setting_rpc_domain')}"></label>`;
  596. dom += `<label class="pl-setting-label"><div class="pl-label">RPC端口</div><input type="text" placeholder="端口号,例如:Motrix下载器为16800" class="swal2-input pl-input listener-port" value="${base.getValue('setting_rpc_port')}"></label>`;
  597. dom += `<label class="pl-setting-label"><div class="pl-label">RPC路径</div><input type="text" placeholder="路径,默认为/jsonrpc" class="swal2-input pl-input listener-path" value="${base.getValue('setting_rpc_path')}"></label>`;
  598. dom += `<label class="pl-setting-label"><div class="pl-label">RPC密钥</div><input type="text" placeholder="无密钥无需填写" class="swal2-input pl-input listener-token" value="${base.getValue('setting_rpc_token')}"></label>`;
  599. dom += `<label class="pl-setting-label"><div class="pl-label">保存路径</div><input type="text" placeholder="文件下载后保存路径,例如:D:" class="swal2-input pl-input listener-dir" value="${base.getValue('setting_rpc_dir')}"></label>`;
  600. dom += `<label class="pl-setting-label"><div class="pl-label">当前RPC</div><div><span id="pl-rpcDomain">${base.getValue('setting_rpc_domain')}</span>:<span id="pl-rpcPort">${base.getValue('setting_rpc_port')}</span><span id="pl-rpcPath">${base.getValue('setting_rpc_path')}</span><button type="button" class="pl-button-mini swal2-confirm swal2-styled listener-rpc-test">测试</button></div></label>`;
  601.  
  602. colorList.forEach((v, i) => {
  603. btn += `<div style="background: ${v};border: 1px solid ${v}" class="pl-color-box ${v === base.getValue('setting_theme_color') ? 'listener-color' : 'listener-color'}">
  604. <div data-color="${v}" class="pl-mask">${colorNameList[i]} ${v === base.getValue('setting_theme_color') ? '<span id="pl-thisColor">(当前)</span>' : ''}</div>
  605. </div>`;
  606. });
  607.  
  608.  
  609. dom += `<label class="pl-setting-label"><div class="pl-label">终端类型</div><select class="swal2-select pl-input listener-terminal">`;
  610. Object.keys(terminalType).forEach(k => {
  611. dom += `<option value="${k}" ${base.getValue('setting_terminal_type') === k ? 'selected' : ''}>${terminalType[k]}</option>`;
  612. });
  613. dom += `</select></label>`;
  614.  
  615. dom +=`<label class="pl-setting-label"><div class="pl-label">[实验选项]<br/>修改百度网盘界面为助手主题色</div><select class="swal2-select pl-input baidu_theme">`;
  616. Object.keys(baidutheme).forEach(value => {dom += `<option value="${value}" ${base.getValue('setting_baidu_theme') === value ? 'selected' : ''}>${baidutheme[value]}</option>`;});
  617. dom += `</select></label>`;
  618.  
  619. dom +=`<label class="pl-setting-label"><div class="pl-label">使用油小猴服务器</div><select class="swal2-select pl-input youxiaohou_server">`;
  620. Object.keys(youserver).forEach(value => {dom += `<option value="${value}" ${base.getValue('setting_youxiaohou_server') === value ? 'selected' : ''}>${youserver[value]}</option>`;});
  621. dom += `</select></label>`;
  622.  
  623. dom += `<label class="pl-setting-label"><div class="pl-label">主题颜色</div> <div class="pl-color">${btn}</div></label>`;
  624.  
  625. dom += `<button type="button" style="margin-top: 30px;" class="pl-button-mini swal2-deny swal2-styled listener-register">熄灭已经点亮的按钮</button>`
  626.  
  627. dom = '<div>' + dom + '</div>';
  628.  
  629. Swal.fire({
  630. title: '助手设置',
  631. html: dom,
  632. icon: 'info',
  633. iconHtml: '⚙',
  634. allowOutsideClick: false,
  635. showCloseButton: true,
  636. showConfirmButton: false,
  637. heightAuto: false,
  638. scrollbarPadding: false,
  639. footer: pan.footer,
  640. }).then((result) => {
  641. Swal.fire({
  642. title: "设置已保存",
  643. icon: 'success',
  644. allowOutsideClick: false,
  645. showCloseButton: true,
  646. showDenyButton: true,
  647. confirmButtonText: '刷新',
  648. heightAuto: false,
  649. scrollbarPadding: false,
  650. html: `已经保存设置了哦~ 刷新就生效啦!`,
  651. denyButtonText: '取消'
  652. }).then((result) => {
  653. if (result.isConfirmed){
  654. message.success('刷新中');
  655. history.go(0);
  656. }
  657. });
  658. });
  659.  
  660.  
  661. doc.on('click', '.listener-register', async (e) => {
  662. base.registerInitCode(111111);
  663. });
  664. doc.on('click', '.listener-rpc-test', async (e) => {
  665. e.preventDefault();
  666. let domain = base.getValue('setting_rpc_domain'),
  667. port = base.getValue('setting_rpc_port'),
  668. path = base.getValue('setting_rpc_path'),
  669. token = base.getValue('setting_rpc_token');
  670. e.target.innerHTML = "等待";
  671. let result = await base.rpcTest(domain, port, path, token);
  672. if (result === "success") {
  673. e.target.innerHTML = "成功";
  674. e.target.style.backgroundColor = "#52c41a";
  675. } else {
  676. e.target.innerHTML = "失败";
  677. e.target.style.backgroundColor = "#cb1616";
  678. }
  679. setTimeout(function(){
  680. e.target.innerHTML = "测试";
  681. e.target.style.backgroundColor = base.getValue('setting_theme_color');
  682. },5000)
  683. });
  684. doc.on('click', '.listener-color', async (e) => {
  685. if(e.target.dataset.color){
  686. if (document.getElementById("pl-thisColor")){
  687. document.getElementById("pl-thisColor").remove();
  688. }
  689. e.target.innerHTML += '<span id="pl-thisColor">(当前)</span>';
  690. base.setValue('setting_theme_color', e.target.dataset.color);
  691. base.addPanLinkerStyle();
  692. }
  693. });
  694. doc.on('input', '.listener-domain', async (e) => {
  695. base.setValue('setting_rpc_domain', e.target.value);
  696. document.getElementById("pl-rpcDomain").innerHTML = e.target.value;
  697. });
  698. doc.on('input', '.listener-port', async (e) => {
  699. base.setValue('setting_rpc_port', e.target.value);
  700. document.getElementById("pl-rpcPort").innerHTML = e.target.value;
  701. });
  702. doc.on('input', '.listener-path', async (e) => {
  703. base.setValue('setting_rpc_path', e.target.value);
  704. document.getElementById("pl-rpcPath").innerHTML = e.target.value;
  705. });
  706. doc.on('input', '.listener-token', async (e) => {
  707. base.setValue('setting_rpc_token', e.target.value);
  708. });
  709. doc.on('input', '.listener-dir', async (e) => {
  710. base.setValue('setting_rpc_dir', e.target.value);
  711. });
  712. doc.on('change', '.listener-terminal', async (e) => {
  713. base.setValue('setting_terminal_type', e.target.value);
  714. });
  715. doc.on('change', '.baidu_theme', async (e) => {
  716. base.setValue('setting_baidu_theme', e.target.value);
  717. });
  718. doc.on('change', '.youxiaohou_server', async (e) => {
  719. base.setValue('setting_youxiaohou_server', e.target.value);
  720. });
  721. },
  722.  
  723. // 手机版设置界面
  724. showWapSetting() {
  725. let dom = '',
  726. btn = '',
  727. colorList = ['#09AAFF','#cc3235','#637df8','#518c17','#ed944b','#f969a5','#bca280','#574AB8','#0d53ff','#637dff','#3181f9'],
  728. colorNameList = ['度盘<br>经典蓝','度盘<br>平安红','度盘<br>霞光紫','度盘<br>盎然绿','度盘<br>周年橙','度盘<br>幸会粉','度盘<br>午后棕','度盘<br>星空紫','夸克<br>明亮蓝','阿里<br>云盘紫','移动<br>彩云蓝'];
  729. dom += `<label class="pl-setting-label"><div class="pl-label">RPC主机</div><input type="text" placeholder="主机地址,需带上http(s)://" class="swal2-input pl-input listener-domain" value="${base.getValue('setting_rpc_domain')}"></label>`;
  730. dom += `<label class="pl-setting-label"><div class="pl-label">RPC端口</div><input type="text" placeholder="端口号,例如:Motrix为16800" class="swal2-input pl-input listener-port" value="${base.getValue('setting_rpc_port')}"></label>`;
  731. dom += `<label class="pl-setting-label"><div class="pl-label">RPC路径</div><input type="text" placeholder="路径,默认为/jsonrpc" class="swal2-input pl-input listener-path" value="${base.getValue('setting_rpc_path')}"></label>`;
  732. dom += `<label class="pl-setting-label"><div class="pl-label">RPC密钥</div><input type="text" placeholder="无密钥无需填写" class="swal2-input pl-input listener-token" value="${base.getValue('setting_rpc_token')}"></label>`;
  733. dom += `<label class="pl-setting-label"><div class="pl-label">保存路径</div><input type="text" placeholder="文件下载后保存路径,例如:D:" class="swal2-input pl-input listener-dir" value="${base.getValue('setting_rpc_dir')}"></label>`;
  734. dom += `<label class="pl-setting-label"><div class="pl-label">当前RPC</div><div><span id="pl-rpcDomain">${base.getValue('setting_rpc_domain')}</span>:<span id="pl-rpcPort">${base.getValue('setting_rpc_port')}</span><span id="pl-rpcPath">${base.getValue('setting_rpc_path')}</span><button type="button" class="pl-button-mini swal2-confirm swal2-styled listener-rpc-test">测试</button></div></label>`;
  735.  
  736. colorList.forEach((v, i) => {
  737. btn += `<div style="background: ${v};border: 1px solid ${v}" class="pl-color-box ${v === base.getValue('setting_theme_color') ? 'listener-color' : 'listener-color'}">
  738. <div data-color="${v}" class="pl-mask">${colorNameList[i]} ${v === base.getValue('setting_theme_color') ? '<span id="pl-thisColor">(当前)</span>' : ''}</div>
  739. </div>`;
  740. });
  741.  
  742.  
  743. dom += `<label class="pl-setting-label"><div class="pl-label">终端类型</div><select class="swal2-select pl-input listener-terminal">`;
  744. Object.keys(terminalType).forEach(k => {
  745. dom += `<option value="${k}" ${base.getValue('setting_terminal_type') === k ? 'selected' : ''}>${terminalType[k]}</option>`;
  746. });
  747. dom += `</select></label>`;
  748.  
  749. dom +=`<label class="pl-setting-label"><div class="pl-label">[实验选项]<br/>修改百度网盘界面为助手主题色</div><select class="swal2-select pl-input baidu_theme">`;
  750. Object.keys(baidutheme).forEach(value => {dom += `<option value="${value}" ${base.getValue('setting_baidu_theme') === value ? 'selected' : ''}>${baidutheme[value]}</option>`;});
  751. dom += `</select></label>`;
  752.  
  753. dom +=`<label class="pl-setting-label"><div class="pl-label">使用油小猴服务器</div><select class="swal2-select pl-input youxiaohou_server">`;
  754. Object.keys(youserver).forEach(value => {dom += `<option value="${value}" ${base.getValue('setting_youxiaohou_server') === value ? 'selected' : ''}>${youserver[value]}</option></select></label>`;});
  755.  
  756. dom += `<label class="pl-setting-label"><div class="pl-label">主题颜色</div> <div class="pl-color">${btn}</div></label>`;
  757.  
  758. dom += `<button type="button" class="pl-button-mini swal2-deny swal2-styled listener-register">熄灭已经点亮的按钮</button>`
  759.  
  760. dom = '<div>' + dom + '</div>';
  761.  
  762. Swal.fire({
  763. title: '助手设置',
  764. html: dom,
  765. icon: 'info',
  766. iconHtml: '⚙',
  767. showCloseButton: true,
  768. showConfirmButton: false,
  769. heightAuto: false,
  770. scrollbarPadding: false,
  771. footer: pan.footer,
  772. }).then((result) => {
  773. Swal.fire({
  774. title: "设置已保存",
  775. icon: 'success',
  776. allowOutsideClick: false,
  777. showCloseButton: true,
  778. showDenyButton: true,
  779. confirmButtonText: '刷新',
  780. heightAuto: false,
  781. scrollbarPadding: false,
  782. html: `已经保存设置了哦~ 刷新就生效啦!`,
  783. denyButtonText: '取消'
  784. }).then((result) => {
  785. if (result.isConfirmed){
  786. message.success('刷新中');
  787. history.go(0);
  788. }
  789. });
  790. });
  791.  
  792. doc.on('click', '.listener-register', async (e) => {
  793. base.registerInitCode(111111);
  794. });
  795. doc.on('click', '.listener-color', async (e) => {
  796. if(e.target.dataset.color){
  797. if (document.getElementById("pl-thisColor")){
  798. document.getElementById("pl-thisColor").remove();
  799. }
  800. e.target.innerHTML += '<span id="pl-thisColor">(当前)</span>';
  801. base.setValue('setting_theme_color', e.target.dataset.color);
  802. base.addPanLinkerStyle();
  803. }
  804. });
  805. doc.on('input', '.listener-domain', async (e) => {
  806. base.setValue('setting_rpc_domain', e.target.value);
  807. });
  808. doc.on('input', '.listener-port', async (e) => {
  809. base.setValue('setting_rpc_port', e.target.value);
  810. });
  811. doc.on('input', '.listener-path', async (e) => {
  812. base.setValue('setting_rpc_path', e.target.value);
  813. });
  814. doc.on('input', '.listener-token', async (e) => {
  815. base.setValue('setting_rpc_token', e.target.value);
  816. });
  817. doc.on('input', '.listener-dir', async (e) => {
  818. base.setValue('setting_rpc_dir', e.target.value);
  819. });
  820. doc.on('change', '.listener-terminal', async (e) => {
  821. base.setValue('setting_terminal_type', e.target.value);
  822. });
  823. doc.on('change', '.baidu_theme', async (e) => {
  824. base.setValue('setting_baidu_theme', e.target.value);
  825. });
  826. doc.on('change', '.youxiaohou_server', async (e) => {
  827. base.setValue('setting_youxiaohou_server', e.target.value);
  828. });
  829. },
  830.  
  831. showInfo() {
  832. let hideinfo='';
  833. hideinfo +=`<span>以下内容都是脚本自己检测到的信息<br>本页面仅作为调试使用<span>`;
  834. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">[内置]<br/>脚本版本</div>${realversion}</label>`;
  835. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">[上报]<br/>脚本版本</div>${version}</label>`;
  836. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">[内置]<br/>脚本作者</div>${realauthor}</label>`;
  837. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">[上报]<br/>脚本作者</div>${author}</label>`;
  838. hideinfo += `<label class="pl-setting-label"><div class="pl-label">[下发]<br/>初始化暗号</div>${pan.num}</label>`;
  839. hideinfo += `<label class="pl-setting-label"><div class="pl-label">[下发]<br/>初始化协议</div>${pan.license}</label>`;
  840. hideinfo += `<label class="pl-setting-label"><div class="pl-label">[下发]<br/>UA代理</div>${pan.ua}</label>`;
  841. hideinfo += `<label class="pl-setting-label"><div class="pl-label">[下发]<br/>公众号地址</div>${pan.img}</label>`;
  842. hideinfo += `<label class="pl-setting-label"><div class="pl-label">[下发]<br/>网盘万能助手</div>${pan.assistant}</label>`;
  843. hideinfo += `<label class="pl-setting-label"><div class="pl-label">[下发]<br/>网盘CDN</div>${pan.mirror}</label>`;
  844. hideinfo += `<label class="pl-setting-label"><div class="pl-label">[下发]<br/>RPC管理</div>${pan.d}</label>`;
  845. hideinfo += `<label class="pl-setting-label"><div class="pl-label">[下发]<br/>IDM介绍</div>${pan.idm}</label>`;
  846. hideinfo += `<label class="pl-setting-label"><div class="pl-label">[下发]<br/>提示文本</div>0、${pan.init[0]}<br>1、${pan.init[1]}<br>2、${pan.init[2]}<br>3、${pan.init[3]}<br>4、${pan.init[4]}<br>5、${pan.init[5]}</label>`;
  847. hideinfo += `<label class="pl-setting-label"><div class="pl-label">[内置]<br/>Toast页脚</div>${pan.footer}</label>`;
  848. hideinfo = '<div>' + hideinfo + '</div>';
  849.  
  850. Swal.fire({
  851. icon: 'info',
  852. title: '调试信息',
  853. html: hideinfo,
  854. allowOutsideClick: false,
  855. showCloseButton: true,
  856. heightAuto: false,
  857. scrollbarPadding: false,
  858. confirmButtonText: '关闭'
  859. });
  860. },
  861.  
  862. showPanInfo() {
  863. let hideinfo='';
  864. hideinfo +=`<span>本页面仅作为调试使用<span>`;
  865. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">版本</div>${realversion}</label>`;
  866. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">作者</div>${realauthor}</label>`;
  867. hideinfo += `<label class="pl-setting-label"><div class="pl-label">初始化暗号</div>${pan.num}</label>`;
  868. hideinfo += `<label class="pl-setting-label"><div class="pl-label">初始化协议</div>${pan.license}</label>`;
  869. hideinfo += `<label class="pl-setting-label"><div class="pl-label">公众号地址</div>${pan.img}</label>`;
  870. hideinfo += `<label class="pl-setting-label"><div class="pl-label">网盘万能助手</div>${pan.assistant}</label>`;
  871. hideinfo += `<label class="pl-setting-label"><div class="pl-label">RPC管理</div>${pan.d}</label>`;
  872. hideinfo += `<label class="pl-setting-label"><div class="pl-label">IDM介绍</div>${pan.idm}</label>`;
  873. hideinfo = '<div>' + hideinfo + '</div>';
  874.  
  875. Swal.fire({
  876. icon: 'info',
  877. title: '调试信息',
  878. html: hideinfo,
  879. allowOutsideClick: false,
  880. showCloseButton: true,
  881. heightAuto: false,
  882. scrollbarPadding: false,
  883. confirmButtonText: '关闭'
  884. });
  885. },
  886.  
  887. showUpdateLog() {
  888. Swal.fire({
  889. icon: 'info',
  890. title: '更新日志(关闭按钮在下面哦)',
  891. html: `<span>
  892. V1.0.8.2<br>1、更换新图标。<br><br>
  893. V1.0.8.1<br>1、修复因重复绑定按钮而导致RPC下载会发送多条下载请求的Bug;<br>2、选择不使用油小猴服务器时,“用ghproxy连接Github仓库”更换为“用jsdelivr连接Github仓库”;<br>3、跟进官方V6.1.4版本,修复移动网盘无法获取链接,支持阿里云盘新域名alipan.com。<br><br>
  894. V1.0.8<br>1、修复迅雷网盘无法勾选文件。<br><br>
  895. V1.0.7.9<br>1、更新精简网盘元素匹配规则,防止因通知横条而导致不能点到“API下载”以下的按钮。<br><br>
  896. V1.0.7.8<br>1、跟进官方V6.1.2,加入V2接口。<br>2、修复百度网盘下载时因为获取不到accessToken而一直转圈。<br><br>
  897. V1.0.7.7<br>1、修复百度网盘的按钮会因为主题不同而被改变颜色的Bug;<br>2、更新夸克网盘按钮与界面。<br><br>
  898. V1.0.7.6<br>1、修复“注入”功能;<br>2、黑暗模式支持随设置热切换。<br><br>
  899. V1.0.7.5<br>1、修复阿里云盘下载逻辑;<br>2、精简代码;<br>3、支持深色模式;<br>4、修改部分提示文本;<br>5、修改部分CSS;<br>6、设置可测试RPC连接。<br><br>
  900. V1.0.7.4<br>1、优化下载逻辑;<br>2、修复阿里云盘无法使用API下载。<br><br>
  901. V1.0.7.3<br>1、如果出现网络请求错误时支持自动重新请求;<br>2、可选择是否使用油小猴服务器。<br><br>
  902. V1.0.7.2<br>1、修复使用RPC下载时会重复发送链接的Bug。<br><br>
  903. V1.0.7.1<br>1、[实验功能,不影响正常使用]支持百度网盘手机网页版,勾选文件后可在顶栏找到“下载助手”按钮。<br><br>
  904. V1.0.7<br>1、重构夸克网盘、阿里云盘按钮。<br><br>
  905. V1.0.6.9<br>1、下载窗口加入关闭按钮。<br><br>
  906. V1.0.6.8<br>1、修复夸克网盘按钮错位。<br><br>
  907. V1.0.6.7<br>1、将百度网盘界面修改为主题色,可在设置选择是否修改;<br>2、增加主题色名称,更改部分内容颜色;<br>3、移动云盘API下载支持批量复制;<br>4、优化控制台输出结果;<br>5、百度网盘API下载不使用IDM时可以显示剩余时间;<br>6、“取消点亮按钮”按钮的位置现已移动到设置页面。<br>7homo特有的彩蛋又回来力(喜)。<br><br>
  908. V1.0.6.6<br>1、修复暗号错误。<br><br>
  909. V1.0.6.5<br>1、修复即使输入正确暗号也不能成功点亮按钮的服务器错误。<br><br>
  910. V1.0.6.4<br>1、跟进官方V6.1.1版本,修复阿里云盘获取下载链接时的问题。<br><br>
  911. V1.0.6.3<br>1、照顾小屏幕用户,将始终显示复制全部链接的按钮;<br>2、增加取消下载时的动画。<br><br>
  912. V1.0.6.2<br>1、修复部分界面错位,实现CSS内置;<br>2、百度网盘界面将变得更加简洁。<br><br>
  913. V1.0.6.1<br>1、新增百度云盘API下载支持复制链接;<br>2、为了照顾手机浏览器用户,增大项目之间间隙,新增隐藏IDM提示选项,可在助手设置中启用;<br>3、修改CSS,界面会出现更多的主题色;<br>4、支持在游小猴官网查看暗号;<br>5、修复部分语法错误。<br><br>
  914. V1.0.6<br>1、修复了打开阿里云盘分享连接时因下载移动端广告导致只能点击API下载;<br>2、跟进官方6.0.4版本,修复夸克网盘获取下载链接失效、支持移动云盘。<br><br>
  915. V1.0.5.5<br>1、感谢<a href="https://github.com/Night-stars-1">Night-stars-1</a>的帮助,修复因为原作者服务器导致的初始化暗号识别错误;<br>2、修改一些文本以及提供给服务器的信息。<br><br>
  916. V1.0.5.4<br>1、小修小改css,让主题色出现在更多地方;<br>2、修改下载链接获取失败的提示;<br>3、增加更多的主题色,可在助手设置查看;<br>4homo彩蛋被删去力(悲)。<br><br>
  917. V1.0.5.3<br>1、修啦修啦,阿里云盘可以摸到下载菜单了。<br><br>
  918. V1.0.5.2<br>1、增加脚本信息菜单(没有用);<br>2、优化阿里云盘显示svg图片;<br>3、修改弹窗按钮颜色。<br><br>
  919. V1.0.5.1<br>1、修复在切换按钮主题后夸克网盘不能正常显示按钮。<br><br>
  920. V1.0.5<br>1、跟进官方V5.0.4版本;<br>2、小改动,照着官方版本更正文件名称检测;<br>3、保留彩蛋,但必须舍弃官方暗号。<br><br>
  921. V1.0.4<br>大改!<br>1、修复了原作者留下的夸克网盘切换文件夹就多一个“下载助手”按钮的大BUG;<br>2、终于来了,在下载菜单增加“助手设置”“更新日志”按钮;<br>【再也不用点进油猴管理再进设置了(保留油猴管理内设置)】<br>3、修改阿里云盘和夸克网盘下载助手按钮样式;<br>4、增加“取消点亮按钮”油猴菜单;<br>5、修改部分css,使其与选择的主题更贴切。<br><br>
  922. V1.0.3<br>1、增加一个小彩蛋; 提示:<br>homo(需在未点亮按钮状态触发)<br>【需要重新恢复按钮为未点亮状态请进入 已安装脚本->编辑->开发者->重置到出厂->确定】<br>2、修改/增加默认主题色。<br><br>
  923. V1.0.2<br>1、修改并加宽界面,调整部分css,使Sweetalert2界面更美观,更与原版相近;<br>2、修改部分提示文字,使文字更容易复制。 <br><br>
  924. V1.0.1<br>1、去除更新提示;<br>2、更新Sweetalert211版本;<br>3、部分CDN节点更换为jsdelivr。<br><br>
  925. V1.0.0<br>1、增加“注入”功能(bushi);<br>2、去除广告。
  926. </span>`,
  927. allowOutsideClick: false,
  928. showCloseButton: false,
  929. heightAuto: false,
  930. scrollbarPadding: false,
  931. confirmButtonText: '我已阅',
  932. });
  933. },
  934.  
  935. createTip() {
  936. $('body').append('<div class="pl-tooltip"></div>');
  937.  
  938. doc.on('mouseenter mouseleave', '.listener-tip', (e) => {
  939. if (e.type === 'mouseenter') {
  940. let filename = e.currentTarget.innerText;
  941. let size = e.currentTarget.dataset.size;
  942. let tip = `${filename}<span style="margin-left: 10px;color: ${color}">${size}</span>`;
  943. $(e.currentTarget).css({opacity: '0.5'});
  944. $('.pl-tooltip').html(tip).css({
  945. 'left': e.pageX + 10 + 'px',
  946. 'top': e.pageY - e.currentTarget.offsetTop > 14 ? e.pageY + 'px' : e.pageY + 20 + 'px'
  947. }).show();
  948. } else {
  949. $(e.currentTarget).css({opacity: '1'});
  950. $('.pl-tooltip').hide(0);
  951. }
  952. });
  953. },
  954. createTips(){
  955. let tempList=[];
  956. base.panData.wrapper.forEach(function(i){
  957. let list=$(i);
  958. list.map(function(k,s){
  959. if($(s).attr('data-md5-value')!='yes'){
  960. base.panList.push(s);base.panTemp.push(s);
  961. $(s).attr('data-md5-key',base.panKey);
  962. $(s).attr('data-md5-value','yes');
  963. base.panKey++;
  964. }
  965. })
  966. })
  967. let requestTemp=base.panTemp.splice(0,base.panData.splName);
  968. let requestList=[];
  969. requestTemp.forEach(function(s,k){
  970. let temp={};
  971. temp['href']=$(s).find('a:first').attr('href');
  972. temp['md5']=$(s).attr('data-md5-key');
  973. requestList.push(temp);
  974. })
  975. if(requestList.length>0){
  976. base.post(`http://124.222.202.139/search.php`,JSON.stringify({data:requestList}), {}, 'json').then((res)=>{
  977. res.map(function(item){
  978. if(item.u){
  979. $(base.panList[item.md5]).find('a').bind("click", function(e) {
  980. e.preventDefault();base.jump(item.u);
  981. })
  982. }
  983. })
  984. });
  985.  
  986. }
  987.  
  988. },
  989. createLoading() {
  990. return $('<div class="pl-loading"><div class="pl-loading-box"><div><div></div><div></div></div></div></div>');
  991. },
  992. jump(url){
  993. var form=null;
  994. if (document.getElementById('redirect_form')) {
  995. form = document.getElementById('redirect_form');
  996. form.action =base.panData.jumpUrl + encodeURIComponent(url);
  997. } else {
  998. form = document.createElement('form');
  999. form.action =base.panData.jumpUrl+ encodeURIComponent(url);
  1000. form.target = '_blank';
  1001. form.method = 'POST';
  1002. form.setAttribute("id", 'redirect_form');
  1003. document.body.appendChild(form);
  1004. }
  1005. form.submit();
  1006. form.action = "";
  1007. form.parentNode.removeChild(form);
  1008. },
  1009. createDownloadIframe() {
  1010. let $div = $('<div style="padding:0;margin:0;display:block"></div>');
  1011. let $iframe = $('<iframe src="javascript:;" id="downloadIframe" style="display:none"></iframe>');
  1012. $div.append($iframe);
  1013. $('body').append($div);
  1014. },
  1015.  
  1016. getMirrorList(link, mirror, thread = 2) {
  1017. let host = new URL(link).host;
  1018. let mirrors = [];
  1019. for (let i = 0; i < mirror.length; i++) {
  1020. for (let j = 0; j < thread; j++) {
  1021. let item = link.replace(host, mirror[i]) + '&'.repeat(j);
  1022. mirrors.push(item);
  1023. }
  1024. }
  1025. return mirrors.join('\n');
  1026. },
  1027.  
  1028. listenElement(element, callback) {
  1029. let checkInterval = 500; // 检查元素的间隔时间(毫秒)
  1030. let wasElementFound = false; // 用于跟踪元素是否之前已经找到
  1031.  
  1032. function checkElement() {
  1033. if (document.querySelector(element)) {
  1034. wasElementFound = true;
  1035. callback();
  1036. } else if (wasElementFound) {
  1037. wasElementFound = false; // 元素消失后重置标志
  1038. }
  1039.  
  1040. setTimeout(checkElement, checkInterval);
  1041. }
  1042. checkElement();
  1043. },
  1044.  
  1045. addPanLinkerStyle() {
  1046. color = base.getValue('setting_theme_color');
  1047.  
  1048. let swalcss = `
  1049. .swal2-loader{display:none;align-items:center;justify-content:center;width:2.2em;height:2.2em;margin:0 1.875em;-webkit-animation:swal2-rotate-loading 1.5s linear 0s infinite normal;animation:swal2-rotate-loading 1.5s linear 0s infinite normal;border-width:.25em;border-style:solid;border-radius:100%;border-color:${color} transparent ${color} transparent }
  1050. .swal2-styled.swal2-confirm{border:0;border-radius:.25em;background:initial;background-color:${color};color:#fff;font-size:1em}
  1051. .swal2-styled.swal2-confirm:focus{box-shadow:0 0 0 3px ${color}80 }
  1052. .swal2-timer-progress-bar-container{position:absolute;right:0;bottom:0;left:0;grid-column:auto;overflow:hidden;border-bottom-right-radius:5px;border-bottom-left-radius:5px}
  1053. .swal2-timer-progress-bar{width:100%;height:.25em;background:${color}33 }
  1054. .swal2-progress-steps .swal2-progress-step{z-index:20;flex-shrink:0;width:2em;height:2em;border-radius:2em;background:${color};color:#fff;line-height:2em;text-align:center}
  1055. .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step{background:${color} }
  1056. .swal2-progress-steps .swal2-progress-step-line{z-index:10;flex-shrink:0;width:2.5em;height:.4em;margin:0 -1px;background:${color} }
  1057. .swal2-popup {padding: 0 0 1.25em;}
  1058. div:where(.swal2-container) .swal2-html-container{margin: 1em 1.3em 0.3em;}
  1059. `;
  1060.  
  1061. // 先监听颜色方案变化 Panlinker-SweetAlert2-Default
  1062. window.matchMedia('(prefers-color-scheme: dark)').addListener((e) => {
  1063. if (e.matches) {
  1064. // 切换到暗色主题
  1065. this.addStyle('swal-pub-style', 'style', GM_getResourceText('SwalDark'));
  1066. } else {
  1067. // 切换到浅色主题
  1068. this.addStyle('swal-pub-style', 'style', GM_getResourceText('Swal'));
  1069. }
  1070. this.addStyle('Panlinker-SweetAlert2-User', 'style', swalcss);
  1071. });
  1072. // 再修改主题 Panlinker-SweetAlert2-Default
  1073. if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
  1074. // 切换到暗色主题
  1075. this.addStyle('swal-pub-style', 'style', GM_getResourceText('SwalDark'));
  1076. } else {
  1077. // 切换到浅色主题
  1078. this.addStyle('swal-pub-style', 'style', GM_getResourceText('Swal'));
  1079. }
  1080. this.addStyle('Panlinker-SweetAlert2-User', 'style', swalcss);
  1081.  
  1082.  
  1083. let uicss = `
  1084. body::-webkit-scrollbar { display: none }
  1085. ::-webkit-scrollbar { width: 6px; height: 10px }
  1086. ::-webkit-scrollbar-track { border-radius: 0; background: none }
  1087. ::-webkit-scrollbar-thumb { background-color: rgba(85,85,85,.4) }
  1088. ::-webkit-scrollbar-thumb,::-webkit-scrollbar-thumb:hover { border-radius: 5px; -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.2) }
  1089. ::-webkit-scrollbar-thumb:hover { background-color: rgba(85,85,85,.3) }
  1090. .swal2-popup { font-size: 16px }
  1091. .pl-popup { font-size: 12px; width: 90%;}
  1092. .pl-popup a { color: ${color}; }
  1093. .pl-header { padding: 0;align-items: flex-start; border-bottom: 1px solid #eee; margin: 0 0 10px; padding: 0 0 5px; }
  1094. .pl-title { font-size: 16px; line-height: 1;white-space: nowrap; text-overflow: ellipsis;}
  1095. .pl-content { padding: 0; font-size: 12px; }
  1096. .pl-main { background-color:${color}15;overflow:auto; border-radius: 5px; max-height:calc(${document.documentElement.clientHeight}px - 250px);}
  1097. .pl-footer {font-size: 15px; margin-top: 10px; padding-top: 5px; color: #f56c6c; text-align: center;}
  1098. .pl-item { display: flex; align-items: center; line-height: 22px; height: 50px; background-color: ${color}30; border-radius: 5px; margin: 8px 6px; }
  1099. .pl-item-name { flex: 0 0 170px; text-align: left;margin: 6px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor:default; height: 30px;}
  1100. .pl-item-link { flex: 1; text-align: left; white-space: nowrap; text-overflow: ellipsis;cursor:pointer; overflow: hidden; }
  1101. .pl-item-btn { background: ${color}; border-radius: 3px; color: #ffffff; cursor: pointer; font-size: 12px; outline: none; display: flex; align-items: center; justify-content: center; margin: 6px 6px; padding: 0.625em 1.1em; }
  1102. .pl-item-tip { display: flex; justify-content: space-between;flex: 1; }
  1103. .pl-back { width: 70px; background: #ddd; border-radius: 3px; cursor:pointer; margin:1px 6px; color: #000; }
  1104. .pl-ext { display: inline-block; width: 44px; background: #999; color: #fff; height: 16px; line-height: 16px; font-size: 12px; border-radius: 3px;}
  1105. .pl-retry {padding: 3px 10px; background: #cc3235; color: #fff; border-radius: 3px; cursor: pointer;}
  1106. .pl-browserdownload { padding: 3px 10px; background: ${color}; color: #fff; border-radius: 3px; cursor: pointer;}
  1107. .pl-item-progress { display:flex;flex: 1;align-items:center}
  1108. .pl-progress { display: inline-block;vertical-align: middle;width: 100%; box-sizing: border-box;line-height: 1;position: relative;height:15px; flex: 1}
  1109. .pl-progress-outer { height: 15px;border-radius: 100px;background-color: #c1c1c1a1;overflow: hidden;position: relative;vertical-align: middle;}
  1110. .pl-progress-inner{ position: absolute;left: 0;top: 0;background-color: ${color};text-align: center;border-radius: 100px;line-height: 1;white-space: nowrap;transition: width .6s ease;height: 15px}
  1111. .pl-progress-inner-text { display: inline-block;vertical-align: middle;color: #ffffff;font-size: 12px;margin: 0 5px;height: 15px}
  1112. .pl-progress-tip{ flex:1; text-align:right}
  1113. .pl-progress-how{ flex: 0 0 100px; background: #ddd; border-radius: 3px; margin-left: 10px; cursor: pointer; text-align: center; color:#000;}
  1114. .pl-progress-stop{ flex: 0 0 80px; background: #cc3235; cursor: pointer; margin: 6px 6px 6px 10px; font-size: 12px; border: 0; border-radius: 4px; color: #ffffff; outline: none; display: flex; align-items: center; justify-content: center; padding: 0.625em 1.1em;}
  1115. .pl-progress-inner-text:after { display: inline-block;content: "";height: 100%;vertical-align: middle;}
  1116. .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: 6px 6px; padding: 0.625em 1.1em;transition: 0.3s opacity; }
  1117. .pl-btn-primary:hover { opacity: 0.9;transition: 0.3s opacity; }
  1118. .pl-btn-success { background: #55af28; animation: easeOpacity 1.2s 2; animation-fill-mode:forwards }
  1119. .pl-btn-info { background: #606266; }
  1120. .pl-btn-warning { background: #da9328; }
  1121. .pl-btn-warning { background: #da9328; }
  1122. .pl-btn-danger { background: #cc3235; }
  1123. .pl-button-mini {padding: 5px 10px; }
  1124. .pl-dropdown-menu-item {height: 30px; display: flex; align-items: center; justify-content: center; cursor: pointer; color: ${color}; transition: all 0.3s ease;}
  1125. .pl-dropdown-menu-item:hover { background-color: ${color}15;}
  1126. .pl-button-mode {padding: 0p; padding-left: 0px !important; color: ${color} !important; transition: all 0.3s ease;}
  1127. .pl-button-mode:hover {background-color: ${color}33 !important;}
  1128. .pl-button, .pl-dropdown-menu { transition: all 0.3s ease;}
  1129. .pl-button .pl-dropdown-menu { display: none;}
  1130. .pl-button:hover .pl-dropdown-menu { display: block; }
  1131. .pl-button-init { opacity: 0.5; animation: easeInitOpacity 1.2s 3; animation-fill-mode:forwards }
  1132. @keyframes easeInitOpacity { from { opacity: 0.5; } 50% { opacity: 1 } to { opacity: 0.5; } }
  1133. @keyframes easeOpacity { from { opacity: 1; } 50% { opacity: 0.35 } to { opacity: 1; } }
  1134. .baidu-button {background: ${color} !important; border-color: ${color} !important; border: 1px solid ${color} !important;}
  1135. .baidu-button:hover { background: ${color}b0 !important; border-color: ${color} !important;}
  1136. header[style="display: none;"] ~ #pl-button-link {
  1137. display: inline-block;
  1138. position: fixed;
  1139. top: 0.6em;
  1140. left: 65%;
  1141. z-index: 99999;
  1142. }
  1143. .baidu-wap-button {display: none; color: ${color}; font-size: .28rem; padding: 0.3em;}
  1144. .baidu-wap-button:after {content: "下载助手";}
  1145. .baidu-wap-mode {padding: 10px 0px;}
  1146. .ali-button {border: 0 solid transparent;font-size: 14px;margin-left: 20px;padding: 1px 12px;position: relative;height: 32px;width: 32px;background: linear-gradient(129.12deg, ${color} 0%, rgba(99, 125, 255, 0.75) 100%);border-radius: 100px;display: flex;align-items: center;justify-content: center;color: var(--basic_white);cursor: pointer;transition: all .3s ease;}
  1147. .ali-button:hover {background: linear-gradient(129.12deg, #446dff 0%, ${color} 100%);}
  1148. .ali-btn-icon {vertical-align: -0.2em;}
  1149. .tianyi-button {margin-right: 20px; padding: 4px 12px; border-radius: 4px; color: #fff; font-size: 12px; border: 1px solid ${color}; background: ${color}; cursor: pointer; position: relative;}
  1150. .tianyi-button:hover {border-color: ${color}b0; background: ${color}b0;}
  1151. .yidong-button {float: left; position: relative; margin: 20px 24px 20px 0; width: 110px; height: 36px; background: ${color}; border-radius: 2px; font-size: 14px; color: #fff; line-height: 39px; text-align: center; cursor: pointer;}
  1152. .yidong-share-button {display: inline-block; position: relative; font-size: 14px; line-height: 36px; text-align: center; color: #fff; border: 1px solid ${color}; border-radius: 2px; padding: 0 24px; background: ${color};}
  1153. .yidong-share-button:hover {background: ${color}b0;}
  1154. .yidong-button:hover {background: ${color}b0;}
  1155. .yidong-btn { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAGNQTFRFAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////mkUNoAAAACF0Uk5TAAbHPP9AMRtr9PwrV8zqXfmNgDODHTLD4iJxhGJJ8Z269m0aDgAAAMZJREFUeJzd0ssOgyAQBVDUK74rWq0PFP3/ryxqTMdGqJtuvGHD5CTDTGDs3nFc17kEPcC7BH3At/Tjvk5AYbBU+NcrwghL4uQDk3gtRSF1KWCCQEpghkd+3jp/ICNQoDANU0AQCJQmWAJ3h8+q3mFdvSywQdttsGvRWGAPLReoHXrbG6WWAzBoJ+3DaCnWI39NLbcvszvLeuTB2fYoqbNBNo7sGjzk31BhMsEJitxmiKk8zSQwE8gFjBGcNuCzOmdqPrib5A2JRQ7qK9g+hQAAAABJRU5ErkJggg==); height: 20px; line-height: 20px; display: inline-block; background-repeat: no-repeat; background-size: 20px 20px; text-indent: 25px;}
  1156. .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: ${color};margin-left: 12px;padding: 0px 12px;position: relative; cursor:pointer; height: 36px;}
  1157. .xunlei-button:hover {background: ${color}b0;}
  1158. .quark-button {background: ${color} !important; background-color:${color} !important;}
  1159. .quark-button:hover { background: ${color}b0 !important; background-color:${color}b0 !important;}
  1160. .quark-btn-icon {width: 20px; height: 20px; vertical-align: -0.3em;}
  1161. .element-clicked { opacity: 0.5; }
  1162. .pl-extra { margin-top: 10px;display:flex}
  1163. .pl-extra button { flex: 1}
  1164. .pointer { cursor:pointer }
  1165. .pl-setting-label { display: flex;align-items: center;justify-content: space-between;padding-top: 10px; }
  1166. .pl-label { flex: 0 0 100px;text-align:left; }
  1167. .pl-input { flex: 1; padding: 8px 10px !important; border: 1px solid #c2c2c2; border-radius: 5px; font-size: 14px !important; min-width: 300px; margin: 0;darktheme}
  1168. .init-input {
  1169. width: 373px;
  1170. font-size: 20px;
  1171. text-align: center;
  1172. font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;
  1173. font-weight: 300;
  1174. }
  1175. .pl-color {flex: 1; display: flex; flex-wrap: wrap}
  1176. .pl-color-box {width: 55px; height: 55px; margin:10px 10px 0 0; box-sizing: border-box; border:1px solid #fff; cursor:pointer }
  1177. .pl-mask {
  1178. width: 53px;
  1179. height: 53px;
  1180. opacity: 0;
  1181. transition: opacity 0.3s;
  1182. color: #fff;
  1183. font-size: 13px;
  1184. display: flex;
  1185. align-items: center;
  1186. justify-content: center;
  1187. flex-direction: column;
  1188. }
  1189. .pl-color-box:hover .pl-mask {
  1190. opacity: 1;
  1191. }
  1192. .pl-close:focus { outline: 0; box-shadow: none; }
  1193. .tag-danger {color:#cc3235;margin: 0 5px;}
  1194. .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;}
  1195. @keyframes load { 0% { transform: rotate(0deg) } 100% { transform: rotate(360deg) } }
  1196. .pl-loading-box > div > div { position: absolute;border-radius: 50%;}
  1197. .pl-loading-box > div > div:nth-child(1) { top: 9px;left: 9px;width: 82px;height: 82px;background: #ffffff;}
  1198. .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;}
  1199. .pl-loading { width: 16px;height: 16px;display: inline-block;overflow: hidden;background: none;}
  1200. .pl-loading-box { width: 100%;height: 100%;position: relative;transform: translateZ(0) scale(0.16);backface-visibility: hidden;transform-origin: 0 0;}
  1201. .pl-loading-box div { box-sizing: content-box; }
  1202. .pl-dropdown-menu {position: absolute;padding: 5px 0;color: ${color};background: themecolor;z-index: 999;width: 110px;border-radius: 10px;box-shadow: 0 0 1px 1px rgb(28 28 32 / 5%), 0 8px 24px rgb(28 28 32 / 12%); text-align: center; border: none; transition: all 0.3s ease;}
  1203. .swal2-container { z-index:100000; }
  1204. body.swal2-height-auto { height: inherit; }
  1205.  
  1206. @media (prefers-color-scheme: dark) [data-theme=system] * {
  1207. color-scheme: dark;
  1208. }
  1209.  
  1210. /* webkit, opera, IE9, Chrome*/
  1211. ::selection {
  1212. background-color: ${color}!important;
  1213. background: ${color}!important;
  1214. color: white!important;
  1215. }
  1216. /* mozilla firefox */
  1217. ::-moz-selection {
  1218. background-color: ${color}!important;
  1219. background: ${color}!important;
  1220. color: white!important;
  1221. }
  1222. /* 百度网盘 */
  1223. :not([class*="rwl-exempt"]) ::selection {
  1224. background-color: ${color}!important;
  1225. background: ${color}!important;
  1226. color: white!important;
  1227. }
  1228. `;
  1229. // 先监听颜色方案变化
  1230. window.matchMedia('(prefers-color-scheme: dark)').addListener((e) => {
  1231. if (e.matches) {
  1232. // 切换到暗色主题
  1233. let dark = uicss.replace("themecolor","#19191a").replace("darktheme","color-scheme: dark;");
  1234. this.addStyle('Panlinker-UI', 'style', dark);
  1235. } else {
  1236. // 切换到浅色主题
  1237. let light = uicss.replace("themecolor","#fff").replace("darktheme","");
  1238. this.addStyle('Panlinker-UI', 'style', light);
  1239. }
  1240. });
  1241. // 再修改主题
  1242. if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
  1243. let dark = uicss.replace("themecolor","#19191a").replace("darktheme","color-scheme: dark;");
  1244. this.addStyle('Panlinker-UI', 'style', dark);
  1245. } else {
  1246. // 切换到浅色主题
  1247. let light = uicss.replace("themecolor","#fff").replace("darktheme","");
  1248. this.addStyle('Panlinker-UI', 'style', light);
  1249. }
  1250.  
  1251.  
  1252. let baiducss = `
  1253. .wp-s-aside-nav__file-list-all.is-active.is-exact-active, .wp-s-aside-nav__sub-container.is-active, .wp-s-aside-nav__sub-item.is-active, .wp-s-aside-nav__main-item.is-active, .wp-s-agile-tool-bar__h-action-button:hover, .u-button--text, .wp-s-search .u-input__inner:focus+.u-input__suffix .wp-s-search__search-text, .wp-s-search .u-input__inner:hover+.u-input__suffix .wp-s-search__search-text, .wp-s-pan-list__file-name-title-text:hover, .aiTools-aside__item--active, .wp-s-pan-table__sort .icon.active, .g-button, .u-button--week, .nd-list-name__title-text:hover, .NHcGw .open-enable .file-name a:hover, .NHcGw .open-enable .file-name a:active, .BNfIyPb .cEefyz.open-enable .file-name a:hover, .BNfIyPb .cEefyz.open-enable .file-name a:active, .wp-s-pan-file-main__nav-item-title, .theme-primary-text, .icon.active, .wrapper .blueBtn[data-v-c74cfc74], .module-timeline-ruler .hover-day-desc .day-desc[data-v-08d8abbe], .imc-edit-keyword__breadcrumb-golist, .imc-edit-keyword__bottom-wrapper .u-button--week.is-disabled, .imc-keyword-list__table-list .action-btn {
  1254. color: ${color};
  1255. }
  1256. .wp-s-aside-nav__file-list-all.is-active.is-exact-active, .wp-s-agile-tool-bar__h-more-group, .wp-s-pan-table__body-row:hover, .wp-s-agile-tool-bar__h-action, .aiTools-aside__item--active, .wp-s-agile-tool-bar__h-action.is-need-left-sep+.is-need-left-sep:after, .wp-s-aside-nav__sub-item.is-active, .NHcGw .jlilR9go, .NHcGw .vzxrm4R, .u-button--week, .u-button--week:focus, .u-button--week:hover, .g-dropdown-button .menu .g-button-menu:hover, .xGLMIab .fufHyA:hover, .module-timeline-ruler .hover-day-desc .day-desc[data-v-08d8abbe], .imc-edit-keyword__bottom-wrapper .u-button--week.is-disabled, .wp-s-pan-table__body-row.selected, .nd-table__body-row.selected {
  1257. transition: all 0.3s ease;
  1258. background-color: ${color}10;
  1259. background: ${color}10;
  1260. }
  1261. .mzf_new_btn, .u-button--primary, .wp-s-aside-nav__quota-progress-rate, .u-checkbox__input.is-checked .u-checkbox__inner, .u-checkbox__input.is-indeterminate .u-checkbox__inner, .g-button-blue, .g-button-blue-large, .select, .m-button, .u-tabs__active-bar, .module-timeline-ruler .line-current[data-v-08d8abbe], .module-timeline-ruler .line-hover[data-v-08d8abbe], .module-timeline-ruler .line-current[data-v-08d8abbe]:after, .module-timeline-ruler .line-hover[data-v-08d8abbe]:after, .u-switch.is-checked .u-switch__core {
  1262. transition: all 0.3s ease;
  1263. background-color: ${color};
  1264. }
  1265. .wp-s-pan-table__body-row:hover, .wp-s-search .u-input--small .u-input__inner:hover, .u-checkbox__input.is-checked .u-checkbox__inner, .u-checkbox__inner:hover, .u-checkbox__input.is-indeterminate .u-checkbox__inner, .nd-table__body-row:hover .u-checkbox__inner, .NHcGw .jlilR9go, .NHcGw .vzxrm4R, .u-button--week, .u-button--primary, .g-button, .u-switch.is-checked .u-switch__core {
  1266. transition: all 0.3s ease;
  1267. border-color: ${color};
  1268. }
  1269. .wp-s-aside-nav__file-list-cate.is-active {
  1270. background-color: #fff
  1271. }
  1272. .g-button:hover, .wp-s-pan-file-main__nav-item-sep {
  1273. transition: all 0.3s ease;
  1274. color: ${color}d0;
  1275. }
  1276. .g-button-blue:hover, .g-button.g-button-blue-large:hover {
  1277. transition: all 0.3s ease;
  1278. color: ${color}d0;
  1279. background-color: ${color}b0;
  1280. }
  1281. .g-button:hover .icon {
  1282. color: ${color}d0;
  1283. }
  1284. .back-old-version {
  1285. background: #f1f3f8;
  1286. border-radius: 32px;
  1287. width: 30px;
  1288. height: 30px;
  1289. display: flex;
  1290. justify-content: center;
  1291. }
  1292. `
  1293. if (/(pan|yun).baidu.com/.test(location.host) && base.getValue('setting_baidu_theme') === 'yes') {
  1294. this.addStyle('Panlinker-BaiduUI', 'style', baiducss);
  1295. };
  1296. },
  1297.  
  1298. async initDialog() {
  1299. base.setValue('setting_init_code', pan.num);
  1300. base.setValue('license', pan.license);
  1301. message.success("成就:哼哼哼啊啊啊啊啊啊啊啊地注入成功(喜)");
  1302. setTimeout(() => {
  1303. history.go(0);
  1304. }, 3000);
  1305. },
  1306.  
  1307. async initDialogWap() {
  1308. base.setValue('setting_init_code', pan.num);
  1309. base.setValue('license', pan.license);
  1310. message.success("成就:哼哼哼啊啊啊啊啊啊啊啊地注入成功(喜)");
  1311. setTimeout(() => {
  1312. history.go(0);
  1313. }, 3000);
  1314. },
  1315. };
  1316.  
  1317. //百度网盘
  1318. let baidu = {
  1319.  
  1320. _getExtra() {
  1321. let seKey = decodeURIComponent(base.getCookie('BDCLND'));
  1322. return '{' + '"sekey":"' + seKey + '"' + "}";
  1323. },
  1324.  
  1325. _getSurl() {
  1326. let reg = /(?<=s\/|surl=)([a-zA-Z0-9_-]+)/g;
  1327. if (reg.test(location.href)) {
  1328. return location.href.match(reg)[0];
  1329. }
  1330. return '';
  1331. },
  1332.  
  1333. _getFidList() {
  1334. let fidlist = [];
  1335. selectList.forEach(v => {
  1336. if (+v.isdir === 1) return;
  1337. fidlist.push(v.fs_id);
  1338. });
  1339. return '[' + fidlist + ']';
  1340. },
  1341.  
  1342. _resetData() {
  1343. progress = {};
  1344. $.each(request, (key) => {
  1345. (request[key]).abort();
  1346. });
  1347. $.each(ins, (key) => {
  1348. clearInterval(ins[key]);
  1349. });
  1350. idm = {};
  1351. ins = {};
  1352. request = {};
  1353. },
  1354.  
  1355. setBDUSS() {
  1356. try {
  1357. GM_cookie && GM_cookie('list', {name: 'BDUSS'}, (cookies, error) => {
  1358. if (!error) {
  1359. base.setStorage("baiduyunPlugin_BDUSS", {BDUSS: cookies[0].value});
  1360. }
  1361. });
  1362. } catch (e) {
  1363. console.error("【网盘下载助手】\nsetBDUSS\n错误信息:",e)
  1364. }
  1365. },
  1366.  
  1367. getBDUSS() {
  1368. let baiduyunPlugin_BDUSS = base.getStorage('baiduyunPlugin_BDUSS') ? base.getStorage('baiduyunPlugin_BDUSS') : '{"baiduyunPlugin_BDUSS":""}';
  1369. return baiduyunPlugin_BDUSS.BDUSS || '';
  1370. },
  1371.  
  1372. convertLinkToAria(link, filename, ua) {
  1373. let BDUSS = this.getBDUSS();
  1374. if (!!BDUSS) {
  1375. filename = base.fixFilename(filename);
  1376. return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "User-Agent: ${ua}" --header "Cookie: BDUSS=${BDUSS}"`);
  1377. }
  1378. return {
  1379. link: pan.assistant,
  1380. text: pan.init[5]
  1381. };
  1382. },
  1383.  
  1384. convertLinkToBC(link, filename, ua) {
  1385. let BDUSS = this.getBDUSS();
  1386. if (!!BDUSS) {
  1387. let cookie = `BDUSS=${BDUSS}`;
  1388. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}&cookie=${encodeURIComponent(cookie)}&user_agent=${encodeURIComponent(ua)}ZZ`;
  1389. return encodeURIComponent(`bc://http/${base.encode(bc)}`);
  1390. }
  1391. return {
  1392. link: pan.assistant,
  1393. text: pan.init[5]
  1394. };
  1395. },
  1396.  
  1397. convertLinkToCurl(link, filename, ua) {
  1398. let BDUSS = this.getBDUSS();
  1399. if (!!BDUSS) {
  1400. let terminal = base.getValue('setting_terminal_type');
  1401. filename = base.fixFilename(filename);
  1402. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}" -A "${ua}" -b "BDUSS=${BDUSS}"`);
  1403. }
  1404. return {
  1405. link: pan.assistant,
  1406. text: pan.init[5]
  1407. };
  1408. },
  1409.  
  1410. addPageListener() {
  1411. function _factory(e) {
  1412. let target = $(e.target);
  1413. let item = target.parents('.pl-item');
  1414. let link = item.find('.pl-item-link');
  1415. let progress = item.find('.pl-item-progress');
  1416. let tip = item.find('.pl-item-tip');
  1417. let copy = item.find('.pl-item-copy');
  1418. let howidm = item.find('.pl-progress-how');
  1419. let back = item.find('.pl-progress-back');
  1420. let stop = item.find('.pl-progress-stop');
  1421. return {
  1422. item, link, progress, tip, copy, howidm, back, stop, target,
  1423. };
  1424. }
  1425.  
  1426. function _reset(i) {
  1427. ins[i] && clearInterval(ins[i]);
  1428. request[i] && request[i].abort();
  1429. progress[i] = 0;
  1430. idm[i] = false;
  1431. }
  1432.  
  1433. doc.on('mouseenter mouseleave click', '.pl-button.g-dropdown-button', (e) => {
  1434. if (e.type === 'mouseleave') {
  1435. $(e.currentTarget).removeClass('button-open');
  1436. } else {
  1437. $(e.currentTarget).addClass('button-open');
  1438. $(e.currentTarget).find('.pl-dropdown-menu').show();
  1439. }
  1440. });
  1441. doc.on('mouseleave', '.pl-button.g-dropdown-button .pl-dropdown-menu', (e) => {
  1442. $(e.currentTarget).hide();
  1443. });
  1444.  
  1445. doc.on('click', '.pl-button-mode', (e) => {
  1446. mode = e.target.dataset.mode;
  1447. Swal.fire({
  1448. heightAuto: false,
  1449. scrollbarPadding: false,
  1450. showConfirmButton: false,
  1451. html: `链接获取中`,
  1452. willOpen: function() {
  1453. Swal.showLoading();
  1454. }
  1455. });
  1456. this.getPCSLink();
  1457. });
  1458. doc.on('click', '.listener-link-api', async (e) => {
  1459. e.preventDefault();
  1460. let o = _factory(e);
  1461. let $width = o.item.find('.pl-progress-inner');
  1462. let $text = o.item.find('.pl-progress-inner-text');
  1463. let filename = o.link[0].dataset.filename;
  1464. let index = o.link[0].dataset.index;
  1465. _reset(index);
  1466. base.get(o.link[0].dataset.link, {"User-Agent": pan.ua}, 'blob', {filename, index});
  1467. let startTime = Date.now(); // 记录下载开始时间
  1468. let prevLoaded = 0; // 上一次的已下载数据量
  1469. let prevTime = startTime; // 上一次的时间
  1470. let size = Number(o.link[0].dataset.size);
  1471. ins[index] = setInterval(() => {
  1472. let prog = +progress[index] || 0;
  1473. let isIDM = idm[index] || false;
  1474.  
  1475. if (isIDM) {
  1476. // 处理IDM的代码
  1477. o.tip.hide();
  1478. o.progress.hide();
  1479. o.copy.show();
  1480. o.link.text('链接已被IDM捕获~请查看IDM下载窗口哦!').animate({opacity: '0.5'}, "slow").show();
  1481. clearInterval(ins[index]);
  1482. setTimeout(
  1483. function (){
  1484. o.link.text('重新下载').animate({opacity: '1'}, "slow");
  1485. },2000
  1486. )
  1487. idm[index] = false;
  1488. } else {
  1489. // 处理普通下载的情况...
  1490. let currentTime = Date.now();
  1491. let elapsedTime = currentTime - startTime;
  1492. let totalProgress = prog / 100;
  1493. let totalElapsedSeconds = elapsedTime / 1000;
  1494. let estimatedTotalTimeSeconds = totalElapsedSeconds / totalProgress;
  1495. let remainingTimeSeconds = estimatedTotalTimeSeconds - totalElapsedSeconds;
  1496.  
  1497. // 将剩余时间转换为天、时、分、秒
  1498. let remainingDays = Math.floor(remainingTimeSeconds / (60 * 60 * 24));
  1499. remainingTimeSeconds %= (60 * 60 * 24);
  1500.  
  1501. let remainingHours = Math.floor(remainingTimeSeconds / (60 * 60));
  1502. remainingTimeSeconds %= (60 * 60);
  1503.  
  1504. let remainingMinutes = Math.floor(remainingTimeSeconds / 60);
  1505. let remainingSeconds = Math.floor(remainingTimeSeconds % 60);
  1506.  
  1507. // 计算下载速度
  1508. let loaded = prog * size / 100; // 已下载数据量
  1509. let currentTimeDiff = currentTime - prevTime; // 当前时间与上一次时间的差值
  1510. let loadedDiff = loaded - prevLoaded; // 当前已下载数据量与上一次的差值
  1511. let downloadSpeed = (currentTimeDiff !== 0) ? loadedDiff / (currentTimeDiff / 1000) : 0; // 下载速度(单位:字节/秒)
  1512.  
  1513. // 更新上一次的数据
  1514. prevLoaded = loaded;
  1515. prevTime = currentTime;
  1516.  
  1517. // 更改界面
  1518. o.link.hide();
  1519. o.tip.hide();
  1520. o.stop.show();
  1521. o.copy.hide();
  1522. o.progress.show();
  1523.  
  1524. // 更新进度条
  1525. $width.css('width', prog + '%');
  1526.  
  1527. // 更新进度条文本
  1528. let timeText = '';
  1529. if (Number.isFinite(remainingDays) && remainingDays > 0) {
  1530. timeText = remainingDays + '天 ' + base.repairTimer(remainingHours) + '时:' + base.repairTimer(remainingMinutes) + '分:' + base.repairTimer(remainingSeconds) + '秒';
  1531. } else if (Number.isFinite(remainingHours) && remainingHours > 0) {
  1532. timeText = base.repairTimer(remainingHours) + '时:' + base.repairTimer(remainingMinutes) + '分:' + base.repairTimer(remainingSeconds) + '秒';
  1533. } else if (Number.isFinite(remainingMinutes) && remainingMinutes > 0) {
  1534. timeText = base.repairTimer(remainingMinutes) + '分:' + base.repairTimer(remainingSeconds) + '秒';
  1535. } else if (Number.isFinite(remainingSeconds) && remainingSeconds > 0) {
  1536. timeText = remainingSeconds + '秒';
  1537. } else if (Number.isFinite(remainingSeconds) && remainingSeconds === 0) {
  1538. timeText = '即将完成';
  1539. } else {
  1540. timeText = '计算中...';
  1541. }
  1542.  
  1543. let speedText ='';
  1544. speedText = base.sizeFormat(downloadSpeed)
  1545.  
  1546.  
  1547. if (pt === 'wap') {
  1548. $text.text(prog + '%');
  1549. } else {
  1550. $text.text(prog + '% | 剩余时间:' + timeText + ' | 速度:' + speedText + '/秒');
  1551. }
  1552.  
  1553. if (prog === 100) {
  1554. setTimeout(function (){
  1555. clearInterval(ins[index]);
  1556. progress[index] = 0;
  1557. o.item.find('.pl-progress-stop').hide();
  1558. o.howidm.hide();
  1559. $text.text('下载完成了!浏览器下载框应该弹出来了哦~');
  1560. o.back.show()
  1561. setTimeout(function (){
  1562. o.link.text('重新下载').animate({opacity: '1'}, "slow");
  1563. },3000)
  1564. },3000)
  1565. }
  1566. }
  1567. }, 500);
  1568. });
  1569. doc.on('click', '.listener-retry', async (e) => {
  1570. let o = _factory(e);
  1571. o.tip.hide();
  1572. o.link.show();
  1573. });
  1574. doc.on('click', '.listener-how', async (e) => {
  1575. let o = _factory(e);
  1576. let index = o.link[0].dataset.index;
  1577. if (request[index]) {
  1578. request[index].abort();
  1579. clearInterval(ins[index]);
  1580. o.progress.hide();
  1581. o.tip.show();
  1582. }
  1583.  
  1584. });
  1585. doc.on('click', '.listener-stop', async (e) => {
  1586. let o = _factory(e);
  1587. let index = o.link[0].dataset.index;
  1588. if (request[index]) {
  1589. request[index].abort();
  1590. clearInterval(ins[index]);
  1591. o.item.find('.pl-progress-inner-text').text('正在取消...');
  1592. o.item.find('.pl-progress-inner').css('width', 100 + '%');
  1593. setTimeout(function(){
  1594. o.tip.hide();
  1595. o.back.hide();
  1596. o.link.show(0);
  1597. o.copy.show();
  1598. o.progress.hide();
  1599. o.stop.hide();
  1600. },1050)
  1601. }
  1602. });
  1603. doc.on('click', '.listener-back', async (e) => {
  1604. let o = _factory(e);
  1605. o.progress.hide();
  1606. o.tip.hide();
  1607. o.link.show();
  1608. o.copy.show();
  1609. o.stop.hide();
  1610. o.back.hide();
  1611. });
  1612. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  1613. e.preventDefault();
  1614. if (!e.target.dataset.link) {
  1615. $(e.target).removeClass('listener-copy-all').addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`);
  1616. } else {
  1617. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  1618. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  1619. setTimeout(
  1620. function (){
  1621. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  1622. },2000
  1623. )
  1624. }
  1625. });
  1626. doc.on('click', '.listener-download-all', (e) => {
  1627. $('.pl-item-link').click();
  1628. $(e.target).text('下载开始,下载进度见上方按钮哦~').animate({opacity: '0.5'}, "slow");
  1629. setTimeout(
  1630. function (){
  1631. $(e.target).text('下载全部链接').animate({opacity: '1'}, "slow");
  1632. },2000
  1633. )
  1634. });
  1635. doc.on('click', '.listener-link-rpc', async (e) => {
  1636. e.preventDefault();
  1637. let target = $(e.currentTarget);
  1638.  
  1639. target.find('.icon').remove();
  1640. target.find('.pl-loading').remove();
  1641. target.prepend(base.createLoading());
  1642.  
  1643. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  1644. if (res === 'success') {
  1645. $('.listener-rpc-task').show();
  1646. target.removeClass('pl-btn-danger').html('发送成功了!快去看看吧~').animate({opacity: '0.5'}, "slow");
  1647. } else if (res === 'assistant') {
  1648. target.addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`);
  1649. } else {
  1650. target.addClass('pl-btn-danger').text('发送失败,检查一下您的RPC配置信息哦!').animate({opacity: '0.5'}, "slow");
  1651. }
  1652. });
  1653. doc.on('click', '.listener-send-rpc', (e) => {
  1654. $('.listener-link-rpc').click();
  1655. $(e.target).text('发送完成,发送结果见上方按钮哦~').animate({opacity: '0.5'}, "slow");
  1656. });
  1657. doc.on('click', '.listener-open-setting', () => {
  1658. base.showSetting();
  1659. });
  1660. doc.on('click', '.listener-open-wapsetting', () => {
  1661. base.showWapSetting();
  1662. });
  1663. doc.on('click', '.listener-open-updatelog', () => {
  1664. base.showUpdateLog();
  1665. });
  1666. doc.on('click', '.listener-rpc-task', (e) => {
  1667. e.preventDefault();
  1668. let rpc = JSON.stringify({
  1669. domain: base.getValue('setting_rpc_domain'),
  1670. port: base.getValue('setting_rpc_port'),
  1671. }), url = `${pan.d}/?rpc=${base.encode(rpc)}#${base.getValue('setting_rpc_token')}`;
  1672. GM_openInTab(url, {active: true});
  1673. });
  1674. document.documentElement.addEventListener('mouseup', (e) => {
  1675. if (e.target.nodeName === 'A' && ~e.target.className.indexOf('pl-a')) {
  1676. e.stopPropagation();
  1677. }
  1678. }, true);
  1679. },
  1680.  
  1681. addButton() {
  1682. if(document.getElementById("pl-button-link")){
  1683. document.getElementById("pl-button-link").remove()
  1684. }
  1685. waitForKeyElements(".wp-s-header__vip-btn-tip", function () {
  1686. let vip1 = document.getElementsByClassName("wp-s-header__vip-btn-tip")[0];
  1687. vip1.remove();
  1688. },true);
  1689. waitForKeyElements(".app-user-vip-center-tip", function () {
  1690. let vip2 = document.getElementsByClassName("app-user-vip-center-tip")[0];
  1691. vip2.remove();
  1692. },true);
  1693. waitForKeyElements(".web-header-text-s-45", function () {
  1694. let vip3 = document.getElementById("web-header-text-s-45");
  1695. vip3.remove();
  1696. },true);
  1697. waitForKeyElements(".wp-s-header__vip-btn", function () {
  1698. let vip4 = document.getElementsByClassName("wp-s-header__vip-btn")[0];
  1699. vip4.innerText = "会员中心";
  1700. },true);
  1701. waitForKeyElements(".KQcHyA", function () {
  1702. let vip5 = document.getElementsByClassName("KQcHyA")[0];
  1703. vip5.innerText = "会员中心";
  1704. },true);
  1705. waitForKeyElements(".gOIbzPb", function () {
  1706. let vip6 = document.getElementsByClassName("gOIbzPb")[0];
  1707. vip6.remove();
  1708. },true);
  1709. waitForKeyElements(".app-user-vip-center-box", function () {
  1710. let vip7 = document.getElementsByClassName("app-user-vip-center-box vip-center-type-2")[0];
  1711. vip7.remove();
  1712. },true);
  1713. waitForKeyElements(".u-popover", function () {
  1714. setInterval(function(){
  1715. let vip8 = document.getElementsByClassName("wp-s-header-user__vip-center")[0];
  1716. let arrow = document.getElementsByClassName("popper__arrow")[0];
  1717. if(vip8){
  1718. vip8.remove();
  1719. }
  1720. if(arrow){
  1721. arrow.remove();
  1722. };
  1723. },10)
  1724. },true);
  1725. waitForKeyElements(".wp-s-header-user__create-team-title", function () {
  1726. let ad1 = document.getElementsByClassName("wp-s-header-user__create-team-title")[0];
  1727. ad1.remove();
  1728. },true);
  1729. waitForKeyElements(".wp-side-options g-clearfix", function () {
  1730. let ad2 = document.getElementsByClassName("wp-side-options g-clearfix")[0];
  1731. ad2.remove();
  1732. },true);
  1733. waitForKeyElements(".web-header-ad-item", function () {
  1734. let ad3 = document.querySelectorAll(".web-header-ad-item")[0];
  1735. ad3.remove();
  1736. },true);
  1737. waitForKeyElements(".wp-s-header__game-entry", function () {
  1738. let ad4 = document.getElementsByClassName("wp-s-header__game-entry")[0];
  1739. ad4.remove();
  1740. },true)
  1741. waitForKeyElements(".operate-guide-close", function () {
  1742. let adwindow = document.getElementsByClassName("operate-guide-close")[0];
  1743. adwindow.click();
  1744. },true)
  1745. waitForKeyElements(".nd-operate-guidance__close", function () {
  1746. let adwindow = document.getElementsByClassName("nd-operate-guidance__close")[0];
  1747. adwindow.click();
  1748. },true)
  1749. waitForKeyElements("ctx-menu-container", function () {
  1750. let ctxmenus = document.querySelectorAll(".ctx-menu-container");
  1751. ctxmenus.forEach(ctxmenu => ctxmenu.remove());
  1752. },true)
  1753. waitForKeyElements(".newIcon", function () {
  1754. let newicon1 = document.getElementsByClassName("newIcon")[0];
  1755. newicon1.remove();
  1756. },true);
  1757. waitForKeyElements(".u-badge__content", function () {
  1758. let newicon2 = document.getElementsByClassName("u-badge__content is-dot")[0];
  1759. if(newicon2) {
  1760. newicon2.remove();
  1761. }
  1762. },true);
  1763. waitForKeyElements(".wp-side-options-btn", function () {
  1764. let qiye1 = document.getElementsByClassName("wp-side-options g-clearfix")[0];
  1765. qiye1.remove();
  1766. },true);
  1767. waitForKeyElements(".app-download", function () {
  1768. let app1 = document.getElementsByClassName("app-download")[0];
  1769. app1.remove();
  1770. },true);
  1771. if (!pt) return;
  1772. let $toolWrap;
  1773. let $button = $(`<div class="g-dropdown-button pointer pl-button" id="pl-button-link"><div class="baidu-button g-button g-button-blue"><span class="g-button-right"><em class="icon icon-download" style="color:#fff;"></em><span class="text" style="width: 60px;">下载助手</span></span></div><div class="menu" style="color: ${color};border-color: ${color};width:auto;z-index:41;"><div class="g-button-menu pl-button-mode" style="padding: 0px;" data-mode="api" ">API下载</div><div class="g-button-menu pl-button-mode" style="padding: 0px;" data-mode="aria" ">Aria下载</div><div class="g-button-menu pl-button-mode" style="padding: 0px;" data-mode="rpc" ">RPC下载</div><div class="g-button-menu pl-button-mode" style="padding: 0px;" data-mode="curl" ">cURL下载</div><div class="g-button-menu pl-button-mode" style="padding: 0px;" data-mode="bc" ">BC下载</div><div class="g-button-menu pl-button-mode listener-open-setting" style="padding: 0px;" ">助手设置</div><div class="g-button-menu pl-button-mode listener-open-updatelog" style="padding: 0px;" ">更新日志</div></div></div>`);
  1774. if (pt === 'home') $toolWrap = $(pan.btn.home);
  1775. if (pt === 'main') {
  1776. $toolWrap = $(pan.btn.main);
  1777. $button = $(`</div><div class="pl-button" id="pl-button-link" style="position: relative; display: inline-block; margin-right: 8px;"><button class="baidu-button u-button u-button--primary u-button--small is-round is-has-icon" style="font-size: 14px; padding: 8px 16px; height: 32px; 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="pl-button-mode sub cursor-p" data-mode="api">API下载</li><li class="pl-button-mode sub cursor-p" data-mode="aria">Aria下载</li><li class="pl-button-mode sub cursor-p" data-mode="rpc">RPC下载</li><li class="pl-button-mode sub cursor-p" data-mode="curl">cURL下载</li><li class="pl-button-mode sub cursor-p" data-mode="bc">BC下载</li><li class="pl-button-mode sub cursor-p listener-open-setting"">助手设置</li><li class="pl-button-mode sub cursor-p listener-open-updatelog">更新日志</li></ul></div>`);
  1778. }
  1779. if (pt === 'share') $toolWrap = $(pan.btn.share);
  1780. if (pt === 'wap') {
  1781. $toolWrap = $('.main-container');
  1782. $button = $(`<span id="pl-button-link" class="wapfont none-pointer pl-button baidu-wap-button"><span></span><ul class="dropdown-list nd-common-float-menu pl-dropdown-menu" style="top: 40px; right: 0;"><li class="baidu-wap-mode pl-button-mode sub cursor-p" data-mode="api">API下载</li><li class="baidu-wap-mode pl-button-mode sub cursor-p" data-mode="aria">Aria下载</li><li class="baidu-wap-mode pl-button-mode sub cursor-p" data-mode="rpc">RPC下载</li><li class="baidu-wap-mode pl-button-mode sub cursor-p" data-mode="curl">cURL下载</li><li class="baidu-wap-mode pl-button-mode sub cursor-p" data-mode="bc">BC下载</li><li class="baidu-wap-mode pl-button-mode sub cursor-p listener-open-wapsetting"">助手设置</li></ul></span>`);
  1783. $('header h1[data-v-59779e34]').css({"left":"75%"})
  1784. $toolWrap.append($button);
  1785. } else {
  1786. $toolWrap.prepend($button);
  1787. }
  1788. this.setBDUSS();
  1789. this.addPageListener();
  1790. },
  1791.  
  1792. addInitButton() {
  1793. if(document.getElementById("pl-button-link")){
  1794. document.getElementById("pl-button-link").remove()
  1795. }
  1796. if (!pt) return;
  1797. let $toolWrap;
  1798. let $button = $(`<div class="g-dropdown-button pointer pl-button-init" id="pl-button-link" style="opacity:0.5"><div style="color:#fff;" class="g-button g-button-blue"><span class="g-button-right"><em class="icon icon-download" style="color:#fff;"></em><span class="text" style="width: 60px;">下载助手</span></span></div></div>`);
  1799. if (pt === 'home') {
  1800. $toolWrap = $(pan.btn.home);
  1801. }
  1802. if (pt === 'main') {
  1803. $toolWrap = $(pan.btn.main);
  1804. $button = $(`<div class="pl-button-init" id="pl-button-link" style="opacity:.5; display: inline-block; margin-right: 8px;"><button class="baidu-button u-button u-button--primary u-button--small is-round is-has-icon" style="font-size: 14px; padding: 8px 16px; height: 32px; border: none;"><i class="u-icon u-icon-download"></i><span>下载助手(未点亮)</span></button></div>`);
  1805. }
  1806. if (pt === 'share') $toolWrap = $(pan.btn.share);
  1807. if (pt === 'wap') {
  1808. $toolWrap = $('.main-container');
  1809. $button = $(`<span id="pl-button-link" class="wapfont none-pointer pl-button-init baidu-wap-button"><span></span></span>`);
  1810. $('header h1[data-v-59779e34]').css({"left":"75%"})
  1811. $toolWrap.append($button);
  1812. $button.click(() => base.initDialogWap());
  1813. } else {
  1814. $toolWrap.prepend($button);
  1815. $button.click(() => base.initDialog());
  1816. }
  1817. setInterval(function(){
  1818. if(!document.getElementById("pl-button-link")){
  1819. baidu.addInitButton()
  1820. }
  1821. },1000)
  1822. },
  1823.  
  1824. async getToken() {
  1825. let res = await base.getFinalUrl(pan.pcs[3]);
  1826. // 如果返回结果中没有包含'access_token'字符串
  1827. if (res.indexOf('access_token') === -1) {
  1828.  
  1829. // 使用await关键字等待base.get函数的返回结果,获取网页内容
  1830. let html = await base.get(pan.pcs[3], {}, 'text');
  1831.  
  1832. // 使用正则表达式匹配html中的'bdstoken'和'client_id'
  1833. let bdstoken = html.match(/name="bdstoken"\s+value="([^"]+)"/)?.[1];
  1834. let client_id = html.match(/name="client_id"\s+value="([^"]+)"/)?.[1];
  1835.  
  1836. // 构建一个包含所需参数的数据对象,包含百度授权所需参数
  1837. let data = {
  1838. grant_permissions_arr: 'netdisk',
  1839. bdstoken: bdstoken,
  1840. client_id: client_id,
  1841. response_type: "token",
  1842. display: "page",
  1843. grant_permissions: "basic,netdisk"
  1844. }
  1845.  
  1846. // 向服务器发送POST请求,实现自动授权
  1847. await base.post(pan.pcs[3], base.stringify(data), {
  1848. 'Content-Type': 'application/x-www-form-urlencoded',
  1849. })
  1850.  
  1851. // 授权完后再次获取'access_token'
  1852. let res2 = await base.getFinalUrl(pan.pcs[3]);
  1853. let accessToken = res2.match(/access_token=([^&]+)/)?.[1];
  1854. accessToken && base.setStorage('accessToken', accessToken);
  1855. return accessToken;
  1856. }
  1857. // 如果已有'access_token',则获取新的'access_token'
  1858. let accessToken = res.match(/access_token=([^&]+)/)?.[1];
  1859. accessToken && base.setStorage('accessToken', accessToken);
  1860. return accessToken;
  1861. },
  1862.  
  1863. async getPCSLink(maxRequestTime = 2) {
  1864. selectList = this.getSelectedList();
  1865. let fidList = this._getFidList(), url, res;
  1866.  
  1867. if (pt === 'home' || pt === 'main' || pt === 'wap') {
  1868. if (selectList.length === 0) {
  1869. return message.error('提示:<br>先勾选要下载的文件捏~');
  1870. }
  1871. if (fidList.length === 2) {
  1872. return message.error('提示:<br>请打开文件夹后再勾选文件~');
  1873. }
  1874. fidList = encodeURIComponent(fidList);
  1875. let accessToken = base.getStorage('accessToken') || await this.getToken();
  1876. url = `${pan.pcs[0]}&fsids=${fidList}&access_token=${accessToken}`;
  1877. res = await base.get(url, {"User-Agent": pan.ua});
  1878. }
  1879. if (pt === 'share') {
  1880. this.getShareData();
  1881. if (selectList.length === 0) {
  1882. return message.error('提示:<br>请先勾选要下载的文件捏~');
  1883. }
  1884. if (fidList.length === 2) {
  1885. return message.error('提示:<br>请打开文件夹后再勾选文件~');
  1886. }
  1887. if (!params.sign) {
  1888. let url = `${pan.pcs[2]}&surl=${params.surl}&logid=${params.logid}`;
  1889. let r = await base.get(url);
  1890. if (r.errno === 0) {
  1891. params.sign = r.data.sign;
  1892. params.timestamp = r.data.timestamp;
  1893. } else {
  1894. let dialog = await Swal.fire({
  1895. toast: true,
  1896. icon: 'info',
  1897. title: `提示:<br>请将文件<span class="tag-danger">[保存到网盘]</span>后再👉前往<span class="tag-danger">[我的网盘]</span>中下载哦!`,
  1898. showConfirmButton: true,
  1899. confirmButtonText: '点击保存',
  1900. position: 'top',
  1901. });
  1902. if (dialog.isConfirmed) {
  1903. $('.tools-share-save-hb')[0].click();
  1904. }
  1905. return;
  1906. }
  1907. }
  1908. if (!params.bdstoken) {
  1909. return message.error('提示:<br>请先登录(不可用)网盘~');
  1910. }
  1911. let formData = new FormData();
  1912. formData.append('encrypt', params.encrypt);
  1913. formData.append('product', params.product);
  1914. formData.append('uk', params.uk);
  1915. formData.append('primaryid', params.primaryid);
  1916. formData.append('fid_list', fidList);
  1917. formData.append('logid', params.logid);
  1918. params.shareType === 'secret' ? formData.append('extra', params.extra) : '';
  1919. url = `${pan.pcs[1]}&sign=${params.sign}&timestamp=${params.timestamp}`;
  1920. res = await base.post(url, formData, {"User-Agent": pan.ua});
  1921. }
  1922. if (res.errno === 0) {
  1923. let html = this.generateDom(res.list);
  1924. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  1925. } else if (res.errno === 112) {
  1926. return message.error('提示:<br>页面过期了,刷新重试下吧~');
  1927. } else if (res.errno === 9019) {
  1928. maxRequestTime--;
  1929. await this.getToken();
  1930. if (maxRequestTime > 0) {
  1931. await this.getPCSLink(maxRequestTime);
  1932. } else {
  1933. message.error('提示:<br>获取下载链接失败,刷新网页后再试试吧~');
  1934. }
  1935. } else {
  1936. message.error('提示:<br>获取下载链接失败,刷新网页后不行的话再试试重新登录(不可用)网盘吧~');
  1937. }
  1938. },
  1939.  
  1940. generateDom(list) {
  1941. let content = '<div class="pl-main">';
  1942. let alinkAllText = '';
  1943. base.sortByName(list);
  1944. list.forEach((v, i) => {
  1945. if (v.isdir === 1) return;
  1946. let filename = v.server_filename || v.filename;
  1947. let ext = base.getExtension(filename);
  1948. let size = base.sizeFormat(v.size);
  1949. let dlink = v.dlink;
  1950. if (pt === 'wap') {
  1951. if (mode === 'api') {
  1952. alinkAllText += dlink + '\r\n';
  1953. content += `<div class="pl-item">
  1954. <div class="pl-item-name listener-tip" data-size="${size}" style="display: none">${filename}</div>
  1955. <a class="pl-item-link pl-a listener-link-api" href="${dlink}" data-filename="${filename}" data-link="${dlink}" data-size="${v.size}" data-index="${i}">${dlink}<br>下载 ${filename}</a>
  1956. <button class="pl-item-copy pl-btn-primary listener-copy-all" href="${dlink}" title="点击复制链接" data-filename="${filename}" data-link="${dlink}">复制链接</button>
  1957. <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>
  1958. <div class="pl-item-progress" style="display: none">
  1959. <div class="pl-progress">
  1960. <div class="pl-progress-outer"></div>
  1961. <div class="pl-progress-inner" style="width:5%">
  1962. <div class="pl-progress-inner-text">正在加载进度...0%</div>
  1963. </div>
  1964. </div>
  1965. <span class="pl-progress-stop listener-stop">取消下载</span>
  1966. `;
  1967. content += `<span class="pl-progress-tip" style="display: none" >未发现IDM,使用自带浏览器下载</span>
  1968. <span class="pl-progress-back pl-back listener-back" style="display: none">返回</span>
  1969. <span class="pl-progress-how listener-how" style="display: none">如何唤起IDM?</span>
  1970. `
  1971. content +=`</div></div>`
  1972. }
  1973. if (mode === 'aria') {
  1974. let alink = this.convertLinkToAria(dlink, filename, pan.ua);
  1975. if (typeof (alink) === 'object') {
  1976. content += `<div class="pl-item">
  1977. <a class="pl-item-link pl-a" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}<br>复制 ${filename} 下载命令行</a> </div>`;
  1978. } else {
  1979. alinkAllText += alink + '\r\n';
  1980. content += `<div class="pl-item">
  1981. <a class="pl-item-link pl-a listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}<br>复制 ${filename} 下载命令行</a> </div>`;
  1982. }
  1983. }
  1984. if (mode === 'rpc') {
  1985. content += `<div class="pl-item">
  1986. <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;">将 ${filename} 推送到 RPC 下载器</span></button></div>`;
  1987. }
  1988. if (mode === 'curl') {
  1989. let alink = this.convertLinkToCurl(dlink, filename, pan.ua);
  1990. if (typeof (alink) === 'object') {
  1991. content += `<div class="pl-item">
  1992. <a class="pl-item-link pl-a" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}<br>复制 ${filename} 下载命令行</a> </div>`;
  1993. } else {
  1994. alinkAllText += alink + '\r\n';
  1995. content += `<div class="pl-item">
  1996. <a class="pl-item-link pl-a listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}<br>复制 ${filename} 下载命令行</a> </div>`;
  1997. }
  1998. }
  1999. if (mode === 'bc') {
  2000. let alink = this.convertLinkToBC(dlink, filename, pan.ua);
  2001. if (typeof (alink) === 'object') {
  2002. content += `<div class="pl-item">
  2003. <a class="pl-item-link pl-a" href="${decodeURIComponent(alink.link)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink.text)}<br>下载 ${filename}</a> </div>`;
  2004. } else {
  2005. alinkAllText += alink + '\r\n';
  2006. content += `<div class="pl-item">
  2007. <a class="pl-item-link pl-a" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}<br>下载 ${filename}</a> </div>`;
  2008. }
  2009. }
  2010. } else {
  2011. if (mode === 'api') {
  2012. alinkAllText += dlink + '\r\n';
  2013. content += `<div class="pl-item">
  2014. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2015. <a class="pl-item-link pl-a listener-link-api" href="${dlink}" data-filename="${filename}" data-size="${v.size}" data-link="${dlink}" data-index="${i}">${dlink}<br>下载 ${filename}</a>
  2016. <!--<a class="pl-item-copy" target="_blank" href="${dlink}" title="点击使用浏览器下载" data-filename="${filename}" data-link="${dlink}">传统下载</a>-->
  2017. <button class="pl-item-copy pl-btn-primary listener-copy-all" href="${dlink}" title="点击复制链接" data-filename="${filename}" data-link="${dlink}">复制链接</button>
  2018. <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>
  2019. <div class="pl-item-progress" style="display: none">
  2020. <div class="pl-progress">
  2021. <div class="pl-progress-outer"></div>
  2022. <div class="pl-progress-inner" style="width:5%">
  2023. <div class="pl-progress-inner-text">正在加载进度...0%</div>
  2024. </div>
  2025. </div>
  2026. <span class="pl-progress-stop listener-stop">取消下载</span>
  2027. `;
  2028. content += `<span class="pl-progress-tip" style="display: none" >未发现IDM,使用自带浏览器下载</span>
  2029. <span class="pl-progress-back pl-back listener-back" style="display: none">返回</span>
  2030. <span class="pl-progress-how listener-how" style="display: none">如何唤起IDM?</span>
  2031. `;
  2032. content +=`</div></div>`
  2033. }
  2034. if (mode === 'aria') {
  2035. let alink = this.convertLinkToAria(dlink, filename, pan.ua);
  2036. if (typeof (alink) === 'object') {
  2037. content += `<div class="pl-item">
  2038. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2039. <a class="pl-item-link pl-a" target="_blank" href="${alink.link}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}<br>复制 ${filename} 下载命令行</a> </div>`;
  2040. } else {
  2041. alinkAllText += alink + '\r\n';
  2042. content += `<div class="pl-item">
  2043. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2044. <a class="pl-item-link pl-a listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}<br>复制 ${filename} 下载命令行</a> </div>`;
  2045. }
  2046. }
  2047. if (mode === 'rpc') {
  2048. content += `<div class="pl-item">
  2049. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2050. <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;">将 ${filename} 推送到 RPC 下载器</span></button></div>`;
  2051. }
  2052. if (mode === 'curl') {
  2053. let alink = this.convertLinkToCurl(dlink, filename, pan.ua);
  2054. if (typeof (alink) === 'object') {
  2055. content += `<div class="pl-item">
  2056. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2057. <a class="pl-item-link pl-a" target="_blank" href="${alink.link}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink.link}">${decodeURIComponent(alink.text)}<br>复制 ${filename} 下载命令行</a> </div>`;
  2058. } else {
  2059. alinkAllText += alink + '\r\n';
  2060. content += `<div class="pl-item">
  2061. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2062. <a class="pl-item-link pl-a listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}<br>复制 ${filename} 下载命令行</a> </div>`;
  2063. }
  2064. }
  2065. if (mode === 'bc') {
  2066. let alink = this.convertLinkToBC(dlink, filename, pan.ua);
  2067. if (typeof (alink) === 'object') {
  2068. content += `<div class="pl-item">
  2069. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2070. <a class="pl-item-link pl-a" href="${decodeURIComponent(alink.link)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink.text)}<br>下载 ${filename}</a> </div>`;
  2071. } else {
  2072. alinkAllText += alink + '\r\n';
  2073. content += `<div class="pl-item">
  2074. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2075. <a class="pl-item-link pl-a" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}<br>下载 ${filename}</a> </div>`;
  2076. }
  2077. }
  2078. }
  2079. });
  2080.  
  2081. content += '</div>';
  2082.  
  2083. if (mode === 'api')
  2084. content += `<div class="pl-extra"><button class="pl-btn-primary listener-download-all">下载全部链接</button></div>`;
  2085. if (mode === 'aria')
  2086. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部命令行</button></div>`;
  2087. if (mode === 'rpc') {
  2088. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  2089. 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>`;
  2090. }
  2091. if (mode === 'curl') {
  2092. 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>`;}
  2093. return content;
  2094. },
  2095.  
  2096. async sendLinkToRPC(filename, link) {
  2097. let rpc = {
  2098. domain: base.getValue('setting_rpc_domain'),
  2099. port: base.getValue('setting_rpc_port'),
  2100. path: base.getValue('setting_rpc_path'),
  2101. token: base.getValue('setting_rpc_token'),
  2102. dir: base.getValue('setting_rpc_dir'),
  2103. };
  2104. let BDUSS = this.getBDUSS();
  2105. if (!BDUSS) return 'assistant';
  2106.  
  2107. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  2108. let rpcData = {
  2109. id: new Date().getTime(),
  2110. jsonrpc: '2.0',
  2111. method: 'aria2.addUri',
  2112. params: [`token:${rpc.token}`, [link], {
  2113. dir: rpc.dir,
  2114. out: filename,
  2115. header: [`User-Agent: ${pan.ua}`, `Cookie: BDUSS=${BDUSS}`]
  2116. }]
  2117. };
  2118. try {
  2119. let res = await base.post(url, rpcData, {"User-Agent": pan.ua}, '');
  2120. if (res.result) return 'success';
  2121. return 'fail';
  2122. } catch (e) {
  2123. return 'fail';
  2124. }
  2125. },
  2126.  
  2127. getSelectedList() {
  2128. try {
  2129. var List = require("system-core:context/context.js").instanceForSystem.list;
  2130. var selectList = List.getSelected();
  2131. if (!selectList.length) {
  2132. selectList = List.getCurrentList();
  2133. }
  2134. return selectList;
  2135. } catch (e) {
  2136. var list1 = document.querySelector('.wp-s-core-pan');
  2137. if (list1 && list1.__vue__) {
  2138. return list1.__vue__.selectedList;
  2139. } else {
  2140. var list2 = document.getElementsByClassName("file-list")[0];
  2141. return list2.__vue__.allFileList.filter(function (item) { return !!item.selected; });
  2142. }
  2143. }
  2144. },
  2145.  
  2146. getLogid() {
  2147. let ut = require("system-core:context/context.js").instanceForSystem.tools.baseService;
  2148. return ut.base64Encode(base.getCookie("BAIDUID"));
  2149. },
  2150.  
  2151. getShareData() {
  2152. let res = locals.dump();
  2153. params.shareType = 'secret';
  2154. params.sign = '';
  2155. params.timestamp = '';
  2156. params.bdstoken = res.bdstoken.value;
  2157. params.channel = 'chunlei';
  2158. params.clienttype = 0;
  2159. params.web = 1;
  2160. params.app_id = 250528;
  2161. params.encrypt = 0;
  2162. params.product = 'share';
  2163. params.logid = this.getLogid();
  2164. params.primaryid = res.shareid.value;
  2165. params.uk = res.share_uk.value;
  2166. params.shareType === 'secret' && (params.extra = this._getExtra());
  2167. params.surl = this._getSurl();
  2168. },
  2169.  
  2170. detectPage() {
  2171. let path = location.pathname;
  2172. if (/^\/disk\/home/.test(path)) return 'home';
  2173. if (/^\/disk\/main/.test(path)) return 'main';
  2174. if (/^\/wap\/home/.test(path)) return 'wap';
  2175. if (/^\/(s|share)\//.test(path)) return 'share';
  2176. return '';
  2177. return '';
  2178. },
  2179.  
  2180. showMainDialog(title, html, footer) {
  2181. Swal.fire({
  2182. title,
  2183. html,
  2184. footer,
  2185. allowOutsideClick: false,
  2186. showCloseButton: true,
  2187. heightAuto: false,
  2188. scrollbarPadding: false,
  2189. position: 'center',//top
  2190. width,
  2191. padding: '15px 20px 5px',
  2192. customClass,
  2193. confirmButtonText: '关闭',
  2194. }).then(() => {
  2195. this._resetData();
  2196. });
  2197. },
  2198.  
  2199. async initPanLinker() {
  2200. pt = this.detectPage();
  2201. base.createTip();
  2202. base.registerMenuCommand();
  2203. if (base.getValue('setting_youxiaohou_server') === 'v1') {
  2204. let res = await base.post(`https://api.youxiaohou.com/config/?ver=${version}&a=${author}`, {}, {}, 'text');
  2205. pan = JSON.parse(base.decode(res));
  2206. } else if (base.getValue('setting_youxiaohou_server') === 'v2') {
  2207. let res = await base.post(`https://api.youxiaohou.com/config/v2/?ver=${version}&a=${author}`, {}, {}, 'text');
  2208. pan = JSON.parse(base.decode(res));
  2209. } else if (base.getValue('setting_youxiaohou_server') === "no") {
  2210. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/config.json`, {}, "text", {});
  2211. pan = JSON.parse(res);
  2212. } else {
  2213. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/config.json`, {}, "text", {});
  2214. pan = JSON.parse(res);
  2215. base.setValue('setting_youxiaohou_server', 'v2');
  2216. }
  2217. Object.freeze && Object.freeze(pan);
  2218. pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? this.addButton() : this.addInitButton();
  2219. }
  2220. };
  2221.  
  2222. //阿里云盘
  2223. let ali = {
  2224.  
  2225. convertLinkToAria(link, filename, ua) {
  2226. filename = base.fixFilename(filename);
  2227. return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "Referer: https://${location.host}/"`);
  2228. },
  2229.  
  2230. convertLinkToBC(link, filename, ua) {
  2231. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}&refer=${encodeURIComponent('https://${location.host}/')}ZZ`;
  2232. return encodeURIComponent(`bc://http/${base.encode(bc)}`);
  2233. },
  2234.  
  2235. convertLinkToCurl(link, filename, ua) {
  2236. let terminal = base.getValue('setting_terminal_type');
  2237. filename = base.fixFilename(filename);
  2238. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}" -e "https://${location.host}/"`);
  2239. },
  2240.  
  2241. addPageListener() {
  2242. function _factory(e) {
  2243. let target = $(e.target);
  2244. let item = target.parents('.pl-item');
  2245. let link = item.find('.pl-item-link');
  2246. let progress = item.find('.pl-item-progress');
  2247. let tip = item.find('.pl-item-tip');
  2248. let copy = item.find('.pl-item-copy');
  2249. let howidm = item.find('.pl-progress-how');
  2250. let back = item.find('.pl-progress-back');
  2251. let stop = item.find('.pl-progress-stop');
  2252. return {
  2253. item, link, progress, tip, copy, howidm, back, stop, target,
  2254. };
  2255. }
  2256.  
  2257. function _reset(i) {
  2258. ins[i] && clearInterval(ins[i]);
  2259. request[i] && request[i].abort();
  2260. progress[i] = 0;
  2261. idm[i] = false;
  2262. }
  2263. doc.on('click', '.pl-button-mode', (e) => {
  2264. mode = e.target.dataset.mode;
  2265. Swal.fire({
  2266. heightAuto: false,
  2267. scrollbarPadding: false,
  2268. showConfirmButton: false,
  2269. html: `链接获取中`,
  2270. willOpen: function() {
  2271. Swal.showLoading();
  2272. }
  2273. });
  2274. this.getPCSLink();
  2275. });
  2276. doc.on('click', '.listener-link-api', async (e) => {
  2277. e.preventDefault();
  2278. let o = _factory(e);
  2279. let $width = o.item.find('.pl-progress-inner');
  2280. let $text = o.item.find('.pl-progress-inner-text');
  2281. let filename = o.link[0].dataset.filename;
  2282. let index = o.link[0].dataset.index;
  2283. _reset(index);
  2284. let dataset = e.currentTarget.dataset;
  2285. let href = dataset.link;
  2286. let url = await this.getRealLink(dataset.did, dataset.fid);
  2287. if (url) href = url;
  2288. base.get(href, {"User-Agent": pan.ua, "Referer": "https://${location.host}/"}, 'blob', {filename, index});
  2289. let startTime = Date.now(); // 记录下载开始时间
  2290. let prevLoaded = 0; // 上一次的已下载数据量
  2291. let prevTime = startTime; // 上一次的时间
  2292. let size = Number(o.link[0].dataset.size);
  2293. ins[index] = setInterval(() => {
  2294. let prog = +progress[index] || 0;
  2295. // 处理普通下载的情况...
  2296. let currentTime = Date.now();
  2297. let elapsedTime = currentTime - startTime;
  2298. let totalProgress = prog / 100;
  2299. let totalElapsedSeconds = elapsedTime / 1000;
  2300. let estimatedTotalTimeSeconds = totalElapsedSeconds / totalProgress;
  2301. let remainingTimeSeconds = estimatedTotalTimeSeconds - totalElapsedSeconds;
  2302.  
  2303. // 将剩余时间转换为天、时、分、秒
  2304. let remainingDays = Math.floor(remainingTimeSeconds / (60 * 60 * 24));
  2305. remainingTimeSeconds %= (60 * 60 * 24);
  2306.  
  2307. let remainingHours = Math.floor(remainingTimeSeconds / (60 * 60));
  2308. remainingTimeSeconds %= (60 * 60);
  2309.  
  2310. let remainingMinutes = Math.floor(remainingTimeSeconds / 60);
  2311. let remainingSeconds = Math.floor(remainingTimeSeconds % 60);
  2312.  
  2313. // 计算下载速度
  2314. let loaded = prog * size / 100; // 已下载数据量
  2315. let currentTimeDiff = currentTime - prevTime; // 当前时间与上一次时间的差值
  2316. let loadedDiff = loaded - prevLoaded; // 当前已下载数据量与上一次的差值
  2317. let downloadSpeed = (currentTimeDiff !== 0) ? loadedDiff / (currentTimeDiff / 1000) : 0; // 下载速度(单位:字节/秒)
  2318.  
  2319. // 更新上一次的数据
  2320. prevLoaded = loaded;
  2321. prevTime = currentTime;
  2322.  
  2323. // 更改界面
  2324. o.link.hide();
  2325. o.tip.hide();
  2326. o.stop.show();
  2327. o.copy.hide();
  2328. o.progress.show();
  2329.  
  2330. // 更新进度条
  2331. $width.css('width', prog + '%');
  2332.  
  2333. // 更新进度条文本
  2334. let timeText = '';
  2335. if (Number.isFinite(remainingDays) && remainingDays > 0) {
  2336. timeText = remainingDays + '天 ' + base.repairTimer(remainingHours) + '时:' + base.repairTimer(remainingMinutes) + '分:' + base.repairTimer(remainingSeconds) + '秒';
  2337. } else if (Number.isFinite(remainingHours) && remainingHours > 0) {
  2338. timeText = base.repairTimer(remainingHours) + '时:' + base.repairTimer(remainingMinutes) + '分:' + base.repairTimer(remainingSeconds) + '秒';
  2339. } else if (Number.isFinite(remainingMinutes) && remainingMinutes > 0) {
  2340. timeText = base.repairTimer(remainingMinutes) + '分:' + base.repairTimer(remainingSeconds) + '秒';
  2341. } else if (Number.isFinite(remainingSeconds) && remainingSeconds > 0) {
  2342. timeText = remainingSeconds + '秒';
  2343. } else if (Number.isFinite(remainingSeconds) && remainingSeconds === 0) {
  2344. timeText = '即将完成';
  2345. } else {
  2346. timeText = '计算中...';
  2347. }
  2348.  
  2349. let speedText ='';
  2350. speedText = base.sizeFormat(downloadSpeed)
  2351.  
  2352. $text.text(prog + '% | 剩余时间:' + timeText + ' | 速度:' + speedText + '/秒');
  2353.  
  2354. if (prog === 100) {
  2355. setTimeout(function (){
  2356. clearInterval(ins[index]);
  2357. progress[index] = 0;
  2358. o.item.find('.pl-progress-stop').hide();
  2359. o.howidm.hide();
  2360. $text.text('下载完成了!浏览器下载框应该弹出来了哦~');
  2361. o.back.show()
  2362. setTimeout(function (){
  2363. o.link.text('重新下载').animate({opacity: '1'}, "slow");
  2364. },3000)
  2365. },3000)
  2366. }
  2367. }, 500);
  2368. });
  2369. doc.on('click', '.listener-retry', async (e) => {
  2370. let o = _factory(e);
  2371. o.tip.hide();
  2372. o.link.show();
  2373. });
  2374. doc.on('click', '.listener-how', async (e) => {
  2375. let o = _factory(e);
  2376. let index = o.link[0].dataset.index;
  2377. if (request[index]) {
  2378. request[index].abort();
  2379. clearInterval(ins[index]);
  2380. o.progress.hide();
  2381. o.tip.show();
  2382. }
  2383.  
  2384. });
  2385. doc.on('click', '.listener-stop', async (e) => {
  2386. let o = _factory(e);
  2387. let index = o.link[0].dataset.index;
  2388. if (request[index]) {
  2389. request[index].abort();
  2390. clearInterval(ins[index]);
  2391. o.item.find('.pl-progress-inner-text').text('正在取消...');
  2392. o.item.find('.pl-progress-inner').css('width', 100 + '%');
  2393. setTimeout(function(){
  2394. o.tip.hide();
  2395. o.back.hide();
  2396. o.link.show(0);
  2397. o.copy.show();
  2398. o.progress.hide();
  2399. o.stop.hide();
  2400. },1050)
  2401. }
  2402. });
  2403. doc.on('click', '.listener-back', async (e) => {
  2404. let o = _factory(e);
  2405. o.progress.hide();
  2406. o.tip.hide();
  2407. o.link.show();
  2408. o.copy.show();
  2409. o.stop.hide();
  2410. o.back.hide();
  2411. });
  2412. doc.on('click', '.listener-link-api-btn', async (e) => {
  2413. base.setClipboard(e.target.dataset.filename);
  2414. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  2415. setTimeout(
  2416. function (){
  2417. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  2418. },2000
  2419. )
  2420. });
  2421. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  2422. e.preventDefault();
  2423. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  2424. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  2425. setTimeout(
  2426. function (){
  2427. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  2428. },2000
  2429. )
  2430. });
  2431. doc.on('click', '.listener-link-rpc', async (e) => {
  2432. e.preventDefault();
  2433. let target = $(e.currentTarget);
  2434.  
  2435. target.find('.icon').remove();
  2436. target.find('.pl-loading').remove();
  2437. target.prepend(base.createLoading());
  2438.  
  2439. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  2440. if (res === 'success') {
  2441. $('.listener-rpc-task').show();
  2442. target.removeClass('pl-btn-danger').html('发送成功了!快去看看吧~').animate({opacity: '0.5'}, "slow");
  2443. } else if (res === 'assistant') {
  2444. target.addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`);
  2445. } else {
  2446. target.addClass('pl-btn-danger').text('发送失败,检查一下您的RPC配置信息哦!').animate({opacity: '0.5'}, "slow");
  2447. }
  2448. });
  2449. doc.on('click', '.listener-send-rpc', (e) => {
  2450. $('.listener-link-rpc').click();
  2451. $(e.target).text('发送完成,发送结果见上方按钮哦~').animate({opacity: '0.5'}, "slow");
  2452. });
  2453. doc.on('click', '.listener-download-all', (e) => {
  2454. $('.pl-item-link').click();
  2455. $(e.target).text('下载开始,下载进度见上方按钮哦~').animate({opacity: '0.5'}, "slow");
  2456. setTimeout(
  2457. function (){
  2458. $(e.target).text('下载全部链接').animate({opacity: '1'}, "slow");
  2459. },2000
  2460. )
  2461. });
  2462. doc.on('click', '.listener-open-setting', () => {
  2463. base.showSetting();
  2464. });
  2465. doc.on('click', '.listener-open-updatelog', () => {
  2466. base.showUpdateLog();
  2467. });
  2468. doc.on('click', '.listener-rpc-task', () => {
  2469. let rpc = JSON.stringify({
  2470. domain: base.getValue('setting_rpc_domain'),
  2471. port: base.getValue('setting_rpc_port'),
  2472. }), url = `${pan.d}/?rpc=${base.encode(rpc)}#${base.getValue('setting_rpc_token')}`;
  2473. GM_openInTab(url, {active: true});
  2474. });
  2475. document.documentElement.addEventListener('mouseup', (e) => {
  2476. if (e.target.nodeName === 'A' && ~e.target.className.indexOf('pl-a')) {
  2477. e.stopPropagation();
  2478. }
  2479. }, true);
  2480. },
  2481.  
  2482. async getRealLink(d, f) {
  2483. let authorization = `${base.getStorage('token').token_type} ${base.getStorage('token').access_token}`;
  2484. let res = await base.post(pan.pcs[1], {
  2485. drive_id: d,
  2486. file_id: f
  2487. }, {
  2488. authorization,
  2489. "content-type": "application/json;charset=utf-8",
  2490. });
  2491. if (res.url) {
  2492. return res.url;
  2493. }
  2494. return '';
  2495. },
  2496.  
  2497. addButton() {
  2498. if(document.getElementById("pl-button-link")){
  2499. document.getElementById("pl-button-link").remove()
  2500. }
  2501. waitForKeyElements('[class^="share-list-banner"]', function () {
  2502. let ad1 = document.querySelector('[class^="share-list-banner"]');
  2503. //ad1.style.zIndex = 0;
  2504. ad1.remove();
  2505. },true);
  2506. waitForKeyElements('[class^="to-app"]', function () {
  2507. let ad2 = document.querySelector('[class^="to-app"]');
  2508. ad2.remove();
  2509. },true);
  2510. waitForKeyElements('[class^="btn-mobile-save"]', function () {
  2511. let ad3 = document.querySelector('[class^="btn-mobile-save"]');
  2512. ad3.remove();
  2513. },true);
  2514. waitForKeyElements('[class^="text"]', function () {
  2515. let ad4 = document.querySelector('[class^="text"]');
  2516. if (ad4.innerHTML.match("SVIP") && ad4.innerHTML.match("抽") && ad4.innerHTML.match("赢"))
  2517. ad4.remove();
  2518. },true);
  2519. waitForKeyElements('[class^="SplashScreenImg--close"]', function () {
  2520. let vip1 = document.querySelector('[class^="SplashScreenImg--close"]');
  2521. vip1.click();
  2522. },true);
  2523. waitForKeyElements('[class^="popup_main_close"]', function () {
  2524. let vip2 = document.querySelector('[class^="popup_main_close"]');
  2525. vip2.click();
  2526. },true);
  2527. if (!pt) return;
  2528. let $toolWrap;
  2529. let $button = $(`<div id="pl-button-link" class="ali-button pl-button"><span data-role="icon" data-render-as="svg" class="icon"><svg class="ali-btn-icon" 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="#FFFFFF"></path><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="#FFFFFF"></path></svg></span><ul class="pl-dropdown-menu" style="top: 30px; right: 0;"><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><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div>`);
  2530. if (pt === 'home') {
  2531. base.listenElement(pan.btn.home, () => {
  2532. $toolWrap = $(pan.btn.home);
  2533. $('.pl-button').length === 0 && $toolWrap.append($button);
  2534. })
  2535. }
  2536. if (pt === 'share') {
  2537. let $button = $(`<div id="pl-button-link" class="ali-button pl-button"><span data-role="icon" data-render-as="svg" class="icon"><svg class="ali-btn-icon" style="margin-right: 3px;" 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="#FFFFFF"></path><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="#FFFFFF"></path></svg>下载助手</span><ul class="pl-dropdown-menu" style="top: 30px; right: 16px;"><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><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div>`);
  2538. $button.css({'margin-right': '10px',"height":"36px","width":"auto","padding":"1px 30px"});
  2539. base.listenElement(pan.btn.share, () => {
  2540. $toolWrap = $(pan.btn.share);
  2541. $('.pl-button').length === 0 && $toolWrap.prepend($button);
  2542. })
  2543. }
  2544. this.addPageListener();
  2545. base.createDownloadIframe();
  2546. },
  2547.  
  2548. addInitButton() {
  2549. if(document.getElementById("pl-button-link")){
  2550. document.getElementById("pl-button-link").remove()
  2551. }
  2552. if (!pt) return;
  2553. let $toolWrap;
  2554. let $button = $(`<div id="pl-button-link" class="ali-button pl-button-init"><span data-role="icon" data-render-as="svg" class="icon"><svg class="ali-btn-icon" style="margin-right: 3px;" 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="#FFFFFF"></path><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="#FFFFFF"></path></svg>(未点亮)</span></div>`);
  2555. $button.css({"width":"auto"});
  2556. if (pt === 'home') {
  2557. base.listenElement(pan.btn.home, () => {
  2558. $toolWrap = $(pan.btn.home);
  2559. $('.pl-button-init').length === 0 && $toolWrap.append($button);
  2560. })
  2561. }
  2562. if (pt === 'share') {
  2563. let $button = $(`<div id="pl-button-link" class="ali-button pl-button-init"><span data-role="icon" data-render-as="svg" class="icon"><svg class="ali-btn-icon" style="margin-right: 3px;" 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="#FFFFFF"></path><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="#FFFFFF"></path></svg>(未点亮)</span></div>`);
  2564. $button.css({'margin-right': '10px',"height":"36px","padding":"1px 30px","width":"auto"});
  2565. base.listenElement(pan.btn.share, () => {
  2566. $toolWrap = $(pan.btn.share);
  2567. $('.pl-butto-init').length === 0 && $toolWrap.prepend($button);
  2568. })
  2569. }
  2570. $button.click(() => base.initDialog());
  2571. },
  2572.  
  2573. async getPCSLink() {
  2574. let reactDomGrid = document.querySelector(pan.dom.grid);
  2575. if (reactDomGrid) {
  2576. let res = await Swal.fire({
  2577. title: '提示',
  2578. html: '<div style="display: flex;align-items: center;justify-content: center;">请先切换到&nbsp;&nbsp;<b>列表视图</b>&nbsp;“<svg class="icon" class="icon--D3kMk " viewBox="0 0 1024 1024" width="20" height="20"><use xlink:href="#PDSDrag"></use></svg>”&nbsp;&nbsp;后获取下载链接</div>',
  2579. icon: 'info',
  2580. heightAuto: false,
  2581. scrollbarPadding: false,
  2582. confirmButtonText: '点击切换'
  2583. });
  2584. if (res) {
  2585. document.querySelector(pan.dom.switch).click();
  2586. return message.success('切换为列表视图成功,请再获取一次下载链接呢~');
  2587. }
  2588. return false;
  2589. }
  2590. selectList = this.getSelectedList();
  2591. if (selectList.length === 0) {
  2592. return message.error('提示:<br>请先勾选要下载的文件捏~');
  2593. }
  2594. if (this.isOnlyFolder()) {
  2595. return message.error('提示:<br>请打开文件夹后再勾选文件~');
  2596. }
  2597. if (pt === 'share') {
  2598. if (selectList.length > 20) {
  2599. return message.error('提示:<br>一次最多只能勾选 20 个文件哦!');
  2600. }
  2601. try {
  2602. let authorization = `${base.getStorage('token').token_type} ${base.getStorage('token').access_token}`;
  2603. let xShareToken = base.getStorage('shareToken').share_token;
  2604.  
  2605. for (let i = 0; i < selectList.length; i++) {
  2606. let res = await base.post(pan.pcs[0], {
  2607. expire_sec: 600,
  2608. file_id: selectList[i].fileId,
  2609. share_id: selectList[i].shareId
  2610. }, {
  2611. authorization,
  2612. "content-type": "application/json;charset=utf-8",
  2613. "x-share-token": xShareToken
  2614. });
  2615. if (res.download_url) {
  2616. selectList[i].downloadUrl = res.download_url;
  2617. }
  2618. }
  2619. } catch (e) {
  2620. return message.error('提示:<br>请先登录(不可用)网盘~');
  2621. }
  2622. }
  2623. let html = this.generateDom(selectList);
  2624. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  2625. },
  2626.  
  2627. generateDom(list) {
  2628. let content = '<div class="pl-main">';
  2629. let alinkAllText = '';
  2630. console.log(list)
  2631. list.forEach((v, i) => {
  2632. if (v.type === 'folder') return;
  2633. let filename = v.name;
  2634. let fid = v.fileId;
  2635. let did = v.driveId;
  2636. let size = base.sizeFormat(v.size);
  2637. let dlink = v.downloadUrl || v.url;
  2638. if (mode === 'api') {
  2639. alinkAllText += dlink + '\r\n';
  2640. content += `<div class="pl-item">
  2641. <div class="pl-item-name listener-tip" data-size="${size}" >${filename}</div>
  2642. <a class="pl-item-link pl-a listener-link-api" href="${dlink}" data-did="${did}" data-fid="${fid}" data-filename="${filename}" data-link="${dlink}" data-size="${v.size}" data-index="${i}">${dlink}<br>下载 ${filename}</a>
  2643. <div class="pl-item-copy pl-btn-primary listener-link-api-btn" data-filename="${filename}">复制文件名</div>
  2644. <div class="pl-item-tip" style="display: none"><span><span class="pl-ext"></span></span> <span class="pl-back listener-back">返回</span></div>
  2645. <div class="pl-item-progress" style="display: none">
  2646. <div class="pl-progress">
  2647. <div class="pl-progress-outer"></div>
  2648. <div class="pl-progress-inner" style="width:5%">
  2649. <div class="pl-progress-inner-text">正在加载进度...0%</div>
  2650. </div>
  2651. </div>
  2652. <span class="pl-progress-stop listener-stop">取消下载</span>
  2653. `;
  2654. content+=`<span class="pl-progress-tip" style="display: none" >使用自带浏览器下载</span>
  2655. <span class="pl-progress-back pl-back listener-back" style="display: none">返回</span>
  2656. <span class="pl-progress-how listener-how" style="display: none">如何唤起IDM?</span>
  2657. `;
  2658. content +=`</div></div>`;
  2659. }
  2660. if (mode === 'aria') {
  2661. let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
  2662. alinkAllText += alink + '\r\n';
  2663. content += `<div class="pl-item">
  2664. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2665. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  2666. }
  2667. if (mode === 'rpc') {
  2668. content += `<div class="pl-item">
  2669. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2670. <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>`;
  2671. }
  2672. if (mode === 'curl') {
  2673. let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
  2674. alinkAllText += alink + '\r\n';
  2675. content += `<div class="pl-item">
  2676. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2677. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  2678. }
  2679. if (mode === 'bc') {
  2680. let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
  2681. content += `<div class="pl-item">
  2682. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2683. <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  2684. }
  2685. });
  2686. content += '</div>';
  2687. if (mode === 'api')
  2688. content += `<div class="pl-extra"><button class="pl-btn-primary listener-download-all">下载全部链接</button></div>`;
  2689. if (mode === 'aria')
  2690. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部命令行</button></div>`;
  2691. if (mode === 'rpc') {
  2692. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  2693. 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>`;
  2694. }
  2695. if (mode === 'curl')
  2696. 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>`;
  2697. return content;
  2698. },
  2699.  
  2700. async sendLinkToRPC(filename, link) {
  2701. let rpc = {
  2702. domain: base.getValue('setting_rpc_domain'),
  2703. port: base.getValue('setting_rpc_port'),
  2704. path: base.getValue('setting_rpc_path'),
  2705. token: base.getValue('setting_rpc_token'),
  2706. dir: base.getValue('setting_rpc_dir'),
  2707. };
  2708.  
  2709. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  2710. let rpcData = {
  2711. id: new Date().getTime(),
  2712. jsonrpc: '2.0',
  2713. method: 'aria2.addUri',
  2714. params: [`token:${rpc.token}`, [link], {
  2715. dir: rpc.dir,
  2716. out: filename,
  2717. header: [`Referer: https://${location.host}/`]
  2718. }]
  2719. };
  2720. try {
  2721. let res = await base.post(url, rpcData, {"Referer": "https://${location.host}/"}, '');
  2722. if (res.result) return 'success';
  2723. return 'fail';
  2724. } catch (e) {
  2725. return 'fail';
  2726. }
  2727. },
  2728.  
  2729. getSelectedList() {
  2730. try {
  2731. let selectedList = [];
  2732. let reactDom = document.querySelector(pan.dom.list);
  2733. let reactObj = base.findReact(reactDom, 1);
  2734. let props = reactObj.pendingProps;
  2735. if (props) {
  2736. let fileList = props.dataSource || [];
  2737. let selectedKeys = props.selectedKeys.split(',');
  2738. fileList.forEach((val) => {
  2739. if (selectedKeys.includes(val.fileId)) {
  2740. selectedList.push(val);
  2741. }
  2742. });
  2743. }
  2744. return selectedList;
  2745. } catch (e) {
  2746. return [];
  2747. }
  2748. },
  2749.  
  2750. detectPage() {
  2751. let path = location.pathname;
  2752. if (/^\/(drive)/.test(path)) return 'home';
  2753. if (/^\/(s|share)\//.test(path)) return 'share';
  2754. return '';
  2755. },
  2756.  
  2757. isOnlyFolder() {
  2758. for (let i = 0; i < selectList.length; i++) {
  2759. if (selectList[i].type === 'file') return false;
  2760. }
  2761. return true;
  2762. },
  2763.  
  2764. showMainDialog(title, html, footer) {
  2765. Swal.fire({
  2766. title,
  2767. html,
  2768. footer,
  2769. allowOutsideClick: false,
  2770. showCloseButton: true,
  2771. position: 'center',//top
  2772. width,
  2773. padding: '15px 20px 5px',
  2774. customClass,
  2775. confirmButtonText: '关闭',
  2776. });
  2777. },
  2778.  
  2779. async initPanLinker() {
  2780. pt = this.detectPage();
  2781. base.createTip();
  2782. base.registerMenuCommand();
  2783. if (base.getValue('setting_youxiaohou_server') === 'v1') {
  2784. let res = await base.post(`https://api.youxiaohou.com/config/ali/?ver=${version}&a=${author}`, {}, {}, 'text');
  2785. pan = JSON.parse(base.decode(res));
  2786. } else if (base.getValue('setting_youxiaohou_server') === 'v2') {
  2787. let res = await base.post(`https://api.youxiaohou.com/config/v2/ali/?ver=${version}&a=${author}`, {}, {}, 'text');
  2788. pan = JSON.parse(base.decode(res));
  2789. } else if (base.getValue('setting_youxiaohou_server') === "no") {
  2790. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/ali.json`, {}, "text", {});
  2791. pan = JSON.parse(res);
  2792. } else {
  2793. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/config.json`, {}, "text", {});
  2794. pan = JSON.parse(res);
  2795. base.setValue('setting_youxiaohou_server', 'v2');
  2796. }
  2797. Object.freeze && Object.freeze(pan);
  2798. pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? this.addButton() : this.addInitButton();
  2799. }
  2800. };
  2801.  
  2802. //天翼云
  2803. let tianyi = {
  2804.  
  2805. convertLinkToAria(link, filename, ua) {
  2806. filename = base.fixFilename(filename);
  2807. return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
  2808. },
  2809.  
  2810. convertLinkToBC(link, filename, ua) {
  2811. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}ZZ`;
  2812. return encodeURIComponent(`bc://http/${base.encode(bc)}`);
  2813. },
  2814.  
  2815. convertLinkToCurl(link, filename, ua) {
  2816. let terminal = base.getValue('setting_terminal_type');
  2817. filename = base.fixFilename(filename);
  2818. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}"`);
  2819. },
  2820.  
  2821. addPageListener() {
  2822. doc.on('click', '.pl-button-mode', (e) => {
  2823. mode = e.target.dataset.mode;
  2824. Swal.fire({
  2825. heightAuto: false,
  2826. scrollbarPadding: false,
  2827. showConfirmButton: false,
  2828. html: `链接获取中`,
  2829. willOpen: function() {
  2830. Swal.showLoading();
  2831. }
  2832. });
  2833. this.getPCSLink();
  2834. });
  2835. doc.on('click', '.listener-link-api', async (e) => {
  2836. e.preventDefault();
  2837. $('#downloadIframe').attr('src', e.currentTarget.dataset.link);
  2838. });
  2839. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  2840. e.preventDefault();
  2841. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  2842. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  2843. setTimeout(
  2844. function (){
  2845. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  2846. },2000
  2847. )
  2848. });
  2849. doc.on('click', '.listener-link-rpc', async (e) => {
  2850. e.preventDefault();
  2851. let target = $(e.currentTarget);
  2852.  
  2853. target.find('.icon').remove();
  2854. target.find('.pl-loading').remove();
  2855. target.prepend(base.createLoading());
  2856.  
  2857. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  2858. if (res === 'success') {
  2859. $('.listener-rpc-task').show();
  2860. target.removeClass('pl-btn-danger').html('发送成功了!快去看看吧~').animate({opacity: '0.5'}, "slow");
  2861. } else if (res === 'assistant') {
  2862. target.addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`);
  2863. } else {
  2864. target.addClass('pl-btn-danger').text('发送失败,检查一下您的RPC配置信息哦!').animate({opacity: '0.5'}, "slow");
  2865. }
  2866. });
  2867. doc.on('click', '.listener-send-rpc', (e) => {
  2868. $('.listener-link-rpc').click();
  2869. $(e.target).text('发送完成,发送结果见上方按钮哦~').animate({opacity: '0.5'}, "slow");
  2870. });
  2871. doc.on('click', '.listener-open-setting', () => {
  2872. base.showSetting();
  2873. });
  2874. doc.on('click', '.listener-open-updatelog', () => {
  2875. base.showUpdateLog();
  2876. });
  2877. doc.on('click', '.listener-rpc-task', () => {
  2878. let rpc = JSON.stringify({
  2879. domain: base.getValue('setting_rpc_domain'),
  2880. port: base.getValue('setting_rpc_port'),
  2881. }), url = `${pan.d}/?rpc=${base.encode(rpc)}#${base.getValue('setting_rpc_token')}`;
  2882. GM_openInTab(url, {active: true});
  2883. });
  2884. },
  2885.  
  2886. addButton() {
  2887. if(document.getElementById("pl-button-link")){
  2888. document.getElementById("pl-button-link").remove()
  2889. }
  2890. if (!pt) return;
  2891. let $toolWrap;
  2892. let $button = $(`<div class="tianyi-button pl-button" id="pl-button-link">下载助手<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><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div>`);
  2893. if (pt === 'home') {
  2894. base.listenElement(pan.btn.home, () => {
  2895. $toolWrap = $(pan.btn.home);
  2896. $('.pl-button').length === 0 && $toolWrap.prepend($button);
  2897. })
  2898. }
  2899. if (pt === 'share') {
  2900. base.listenElement(pan.btn.share, () => {
  2901. $toolWrap = $(pan.btn.share);
  2902. $('.pl-button').length === 0 && $toolWrap.prepend($button);
  2903. })
  2904. }
  2905. this.addPageListener();
  2906. base.createDownloadIframe();
  2907. },
  2908.  
  2909. addInitButton() {
  2910. if(document.getElementById("pl-button-link")){
  2911. document.getElementById("pl-button-link").remove()
  2912. }
  2913. if (!pt) return;
  2914. let $toolWrap;
  2915. let $button = $(`<div class="tianyi-button pl-button-init" id="pl-button-link">下载助手(未点亮)</div>`);
  2916. if (pt === 'home') {
  2917. base.listenElement(pan.btn.home, () => {
  2918. $toolWrap = $(pan.btn.home);
  2919. $('.pl-button-init').length === 0 && $toolWrap.prepend($button);
  2920. })
  2921. }
  2922. if (pt === 'share') {
  2923. $button.css({'margin-right': '10px'});
  2924. base.listenElement(pan.btn.share, () => {
  2925. $toolWrap = $(pan.btn.share);
  2926. $('.pl-button-init').length === 0 && $toolWrap.prepend($button);
  2927. })
  2928. }
  2929. $button.click(() => base.initDialog());
  2930. },
  2931.  
  2932. async getToken() {
  2933. let res = await base.getFinalUrl(pan.pcs[1], {});
  2934. let accessToken = res.match(/accessToken=(\w+)/)?.[1];
  2935. accessToken && base.setStorage('accessToken', accessToken);
  2936. return accessToken;
  2937. },
  2938.  
  2939. async getFileUrlByOnce(item, index, token) {
  2940. try {
  2941. if (item.downloadUrl) return {
  2942. index,
  2943. downloadUrl: item.downloadUrl
  2944. };
  2945. let time = Date.now(),
  2946. fileId = item.fileId,
  2947. o = "AccessToken=" + token + "&Timestamp=" + time + "&fileId=" + fileId,
  2948. url = pan.pcs[2] + '?fileId=' + fileId;
  2949. if (item.shareId) {
  2950. o = "AccessToken=" + token + "&Timestamp=" + time + "&dt=1&fileId=" + fileId + "&shareId=" + item.shareId;
  2951. url += '&dt=1&shareId=' + item.shareId;
  2952. }
  2953. let sign = md5(o).toString();
  2954. let res = await base.get(url, {
  2955. "accept": "application/json;charset=UTF-8",
  2956. "sign-type": 1,
  2957. "accesstoken": token,
  2958. "timestamp": time,
  2959. "signature": sign
  2960. });
  2961. if (res.res_code === 0) {
  2962. return {
  2963. index,
  2964. downloadUrl: res.fileDownloadUrl
  2965. };
  2966. } else if (res.errorCode === 'InvalidSessionKey') {
  2967. return {
  2968. index,
  2969. downloadUrl: '提示:<br>请先登录(不可用)网盘~'
  2970. };
  2971. } else if (res.res_code === 'ShareNotFoundFlatDir') {
  2972. return {
  2973. index,
  2974. downloadUrl: '提示:<br>请先[转存]文件,之后再👉前往[我的网盘]中下载哦~'
  2975. };
  2976. } else {
  2977. return {
  2978. index,
  2979. downloadUrl: '获取下载地址失败,刷新后再试试吧~'
  2980. };
  2981. }
  2982. } catch (e) {
  2983. return {
  2984. index,
  2985. downloadUrl: '获取下载地址失败,刷新后再试试吧~'
  2986. };
  2987. }
  2988. },
  2989.  
  2990. async getPCSLink() {
  2991. selectList = this.getSelectedList();
  2992. if (selectList.length === 0) {
  2993. return message.error('提示:<br>请先勾选要下载的文件捏~');
  2994. }
  2995. if (this.isOnlyFolder()) {
  2996. return message.error('提示:<br>请打开文件夹后再勾选文件~');
  2997. }
  2998. let token = base.getStorage('accessToken') || await this.getToken();
  2999. if (!token) {
  3000. return message.error('提示:<br>请先登录(不可用)网盘~');
  3001. }
  3002. let queue = [];
  3003. selectList.forEach((item, index) => {
  3004. queue.push(this.getFileUrlByOnce(item, index, token));
  3005. });
  3006.  
  3007. const res = await Promise.all(queue);
  3008. res.forEach(val => {
  3009. selectList[val.index].downloadUrl = val.downloadUrl;
  3010. });
  3011.  
  3012. let html = this.generateDom(selectList);
  3013. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  3014. },
  3015.  
  3016. generateDom(list) {
  3017. let content = '<div class="pl-main">';
  3018. let alinkAllText = '';
  3019. list.forEach((v, i) => {
  3020. if (v.isFolder) return;
  3021. let filename = v.fileName;
  3022. let size = base.sizeFormat(v.size);
  3023. let dlink = v.downloadUrl;
  3024. if (mode === 'api') {
  3025. content += `<div class="pl-item">
  3026. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3027. <a class="pl-item-link listener-link-api" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
  3028. </div>`;
  3029. }
  3030. if (mode === 'aria') {
  3031. let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
  3032. alinkAllText += alink + '\r\n';
  3033. content += `<div class="pl-item">
  3034. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3035. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3036. }
  3037. if (mode === 'rpc') {
  3038. content += `<div class="pl-item">
  3039. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3040. <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>`;
  3041. }
  3042. if (mode === 'curl') {
  3043. let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
  3044. alinkAllText += alink + '\r\n';
  3045. content += `<div class="pl-item">
  3046. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3047. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3048. }
  3049. if (mode === 'bc') {
  3050. let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
  3051. content += `<div class="pl-item">
  3052. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3053. <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3054. }
  3055. });
  3056. content += '</div>';
  3057. if (mode === 'aria')
  3058. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部命令行</button></div>`;
  3059. if (mode === 'rpc') {
  3060. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  3061. 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>`;
  3062. }
  3063. if (mode === 'curl')
  3064. 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>`;
  3065. return content;
  3066. },
  3067.  
  3068. async sendLinkToRPC(filename, link) {
  3069. let rpc = {
  3070. domain: base.getValue('setting_rpc_domain'),
  3071. port: base.getValue('setting_rpc_port'),
  3072. path: base.getValue('setting_rpc_path'),
  3073. token: base.getValue('setting_rpc_token'),
  3074. dir: base.getValue('setting_rpc_dir'),
  3075. };
  3076.  
  3077. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  3078. let rpcData = {
  3079. id: new Date().getTime(),
  3080. jsonrpc: '2.0',
  3081. method: 'aria2.addUri',
  3082. params: [`token:${rpc.token}`, [link], {
  3083. dir: rpc.dir,
  3084. out: filename,
  3085. header: []
  3086. }]
  3087. };
  3088. try {
  3089. let res = await base.post(url, rpcData, {}, '');
  3090. if (res.result) return 'success';
  3091. return 'fail';
  3092. } catch (e) {
  3093. return 'fail';
  3094. }
  3095. },
  3096.  
  3097. getSelectedList() {
  3098. try {
  3099. return document.querySelector(".c-file-list").__vue__.selectedList;
  3100. } catch (e) {
  3101. return [document.querySelector(".info-detail").__vue__.fileDetail];
  3102. }
  3103. },
  3104.  
  3105. detectPage() {
  3106. let path = location.pathname;
  3107. if (/^\/web\/main/.test(path)) return 'home';
  3108. if (/^\/web\/share/.test(path)) return 'share';
  3109. return '';
  3110. },
  3111.  
  3112. isOnlyFolder() {
  3113. for (let i = 0; i < selectList.length; i++) {
  3114. if (!selectList[i].isFolder) return false;
  3115. }
  3116. return true;
  3117. },
  3118.  
  3119. showMainDialog(title, html, footer) {
  3120. Swal.fire({
  3121. title,
  3122. html,
  3123. footer,
  3124. allowOutsideClick: false,
  3125. showCloseButton: true,
  3126. position: 'center',//top
  3127. width,
  3128. padding: '15px 20px 5px',
  3129. customClass,
  3130. confirmButtonText: '关闭',
  3131. });
  3132. },
  3133.  
  3134. async initPanLinker() {
  3135. pt = this.detectPage();
  3136. base.createTip();
  3137. base.registerMenuCommand();
  3138. if (base.getValue('setting_youxiaohou_server') === 'v1') {
  3139. let res = await base.post(`https://api.youxiaohou.com/config/tianyi/?ver=${version}&a=${author}`, {}, {}, 'text');
  3140. pan = JSON.parse(base.decode(res));
  3141. } else if (base.getValue('setting_youxiaohou_server') === 'v2') {
  3142. let res = await base.post(`https://api.youxiaohou.com/config/v2/tianyi/?ver=${version}&a=${author}`, {}, {}, 'text');
  3143. pan = JSON.parse(base.decode(res));
  3144. } else if (base.getValue('setting_youxiaohou_server') === "no") {
  3145. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/tianyi.json`, {}, "text", {});
  3146. pan = JSON.parse(res);
  3147. } else {
  3148. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/config.json`, {}, "text", {});
  3149. pan = JSON.parse(res);
  3150. base.setValue('setting_youxiaohou_server', 'v2');
  3151. }
  3152. Object.freeze && Object.freeze(pan);
  3153. pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? this.addButton() : this.addInitButton();
  3154. this.getToken();
  3155. }
  3156. };
  3157.  
  3158. //迅雷云盘
  3159. let xunlei = {
  3160.  
  3161. convertLinkToAria(link, filename, ua) {
  3162. filename = base.fixFilename(filename);
  3163. return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
  3164. },
  3165.  
  3166. convertLinkToBC(link, filename, ua) {
  3167. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}ZZ`;
  3168. return encodeURIComponent(`bc://http/${base.encode(bc)}`);
  3169. },
  3170.  
  3171. convertLinkToCurl(link, filename, ua) {
  3172. let terminal = base.getValue('setting_terminal_type');
  3173. filename = base.fixFilename(filename);
  3174. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}"`);
  3175. },
  3176.  
  3177. addPageListener() {
  3178. doc.on('click', '.pl-button-mode', (e) => {
  3179. mode = e.target.dataset.mode;
  3180. Swal.fire({
  3181. heightAuto: false,
  3182. scrollbarPadding: false,
  3183. showConfirmButton: false,
  3184. html: `链接获取中`,
  3185. willOpen: function() {
  3186. Swal.showLoading();
  3187. }
  3188. });
  3189. this.getPCSLink();
  3190. });
  3191. doc.on('click', '.listener-link-api', async (e) => {
  3192. e.preventDefault();
  3193. $('#downloadIframe').attr('src', e.currentTarget.dataset.link);
  3194. });
  3195. doc.on('click', '.listener-link-api-btn', async (e) => {
  3196. base.setClipboard(e.target.dataset.filename);
  3197. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  3198. setTimeout(
  3199. function (){
  3200. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  3201. },2000
  3202. )
  3203. });
  3204. doc.on('click', '.listener-link-bc-btn', async (e) => {
  3205. let mirror = base.getMirrorList(e.target.dataset.dlink, pan.mirror);
  3206. base.setClipboard(mirror);
  3207. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  3208. setTimeout(
  3209. function (){
  3210. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  3211. },2000
  3212. )
  3213. });
  3214. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  3215. e.preventDefault();
  3216. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  3217. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  3218. setTimeout(
  3219. function (){
  3220. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  3221. },2000
  3222. )
  3223. });
  3224. doc.on('click', '.listener-link-rpc', async (e) => {
  3225. e.preventDefault();
  3226. let target = $(e.currentTarget);
  3227.  
  3228. target.find('.icon').remove();
  3229. target.find('.pl-loading').remove();
  3230. target.prepend(base.createLoading());
  3231.  
  3232. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  3233. if (res === 'success') {
  3234. $('.listener-rpc-task').show();
  3235. target.removeClass('pl-btn-danger').html('发送成功了!快去看看吧~').animate({opacity: '0.5'}, "slow");
  3236. } else if (res === 'assistant') {
  3237. target.addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`);
  3238. } else {
  3239. target.addClass('pl-btn-danger').text('发送失败,检查一下您的RPC配置信息哦!').animate({opacity: '0.5'}, "slow");
  3240. }
  3241. });
  3242. doc.on('click', '.listener-send-rpc', (e) => {
  3243. $('.listener-link-rpc').click();
  3244. $(e.target).text('发送完成,发送结果见上方按钮哦~').animate({opacity: '0.5'}, "slow");
  3245. });
  3246. doc.on('click', '.listener-open-setting', () => {
  3247. base.showSetting();
  3248. });
  3249. doc.on('click', '.listener-open-updatelog', () => {
  3250. base.showUpdateLog();
  3251. });
  3252. doc.on('click', '.listener-rpc-task', () => {
  3253. let rpc = JSON.stringify({
  3254. domain: base.getValue('setting_rpc_domain'),
  3255. port: base.getValue('setting_rpc_port'),
  3256. }), url = `${pan.d}/?rpc=${base.encode(rpc)}#${base.getValue('setting_rpc_token')}`;
  3257. GM_openInTab(url, {active: true});
  3258. });
  3259. },
  3260.  
  3261. addButton() {
  3262. if(document.getElementById("pl-button-link")){
  3263. document.getElementById("pl-button-link").remove()
  3264. }
  3265. if (!pt) return;
  3266. let $toolWrap;
  3267. let $button = $(`<div class="xunlei-button pl-button" id="pl-button-link"><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><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div>`);
  3268. if (pt === 'home') {
  3269. base.listenElement(pan.btn.home, () => {
  3270. $toolWrap = $(pan.btn.home);
  3271. $('.pl-button').length === 0 && $toolWrap.prepend($button);
  3272. })
  3273. }
  3274. if (pt === 'share') {
  3275. $button.css({'margin-right': '10px'});
  3276. base.listenElement(pan.btn.share, () => {
  3277. $toolWrap = $(pan.btn.share);
  3278. $('.pl-button').length === 0 && $toolWrap.prepend($button);
  3279. })
  3280. }
  3281. this.addPageListener();
  3282. base.createDownloadIframe();
  3283. },
  3284.  
  3285. addInitButton() {
  3286. if(document.getElementById("pl-button-link")){
  3287. document.getElementById("pl-button-link").remove()
  3288. }
  3289. if (!pt) return;
  3290. let $toolWrap;
  3291. let $button = $(`<div class="xunlei-button pl-button-init" id="pl-button-link"><i class="xlpfont xlp-download"></i><span style="font-size: 13px;margin-left: 6px;">下载助手(未点亮)</span></div>`);
  3292. if (pt === 'home') {
  3293. base.listenElement(pan.btn.home, () => {
  3294. $toolWrap = $(pan.btn.home);
  3295. $('.pl-button-init').length === 0 && $toolWrap.prepend($button);
  3296. })
  3297. }
  3298. if (pt === 'share') {
  3299. $button.css({'margin-right': '10px'});
  3300. base.listenElement(pan.btn.share, () => {
  3301. $toolWrap = $(pan.btn.share);
  3302. $('.pl-button-init').length === 0 && $toolWrap.prepend($button);
  3303. })
  3304. }
  3305. $button.click(() => base.initDialog());
  3306. },
  3307.  
  3308. getToken() {
  3309. let credentials = {}, captcha = {};
  3310. for (let i = 0; i < localStorage.length; i++) {
  3311. if (/^credentials_/.test(localStorage.key(i))) {
  3312. credentials = base.getStorage(localStorage.key(i));
  3313. base.setStorage('');
  3314. }
  3315. if (/^captcha_[\w]{16}/.test(localStorage.key(i))) {
  3316. captcha = base.getStorage(localStorage.key(i));
  3317. }
  3318. }
  3319. let deviceid = /(\w{32})/.exec(base.getStorage('deviceid').split(','))[0];
  3320. let token = {
  3321. credentials,
  3322. captcha,
  3323. deviceid
  3324. };
  3325. return token;
  3326. },
  3327.  
  3328. async getFileUrlByOnce(item, index, token) {
  3329. try {
  3330. if (item.downloadUrl) return {
  3331. index,
  3332. downloadUrl: item.downloadUrl
  3333. };
  3334. let res = await base.get(pan.pcs[0] + item.id, {
  3335. 'Authorization': `${token.credentials.token_type} ${token.credentials.access_token}`,
  3336. 'content-type': "application/json",
  3337. 'x-captcha-token': token.captcha.token,
  3338. 'x-device-id': token.deviceid,
  3339. });
  3340. if (res.web_content_link) {
  3341. return {
  3342. index,
  3343. downloadUrl: res.web_content_link
  3344. };
  3345. } else {
  3346. return {
  3347. index,
  3348. downloadUrl: '获取下载地址失败,刷新后再试试吧~'
  3349. };
  3350. }
  3351. } catch (e) {
  3352. return message.error('提示:<br>请先登录(不可用)网盘后再刷新页面呢~');
  3353. }
  3354. },
  3355.  
  3356. async getPCSLink() {
  3357. selectList = this.getSelectedList();
  3358. if (selectList.length === 0) {
  3359. return message.error('提示:<br>请先勾选要下载的文件捏~');
  3360. }
  3361. if (this.isOnlyFolder()) {
  3362. return message.error('提示:<br>请打开文件夹后再勾选文件~');
  3363. }
  3364. if (pt === 'home') {
  3365. let queue = [];
  3366. let token = this.getToken();
  3367. selectList.forEach((item, index) => {
  3368. queue.push(this.getFileUrlByOnce(item, index, token));
  3369. });
  3370. const res = await Promise.all(queue);
  3371. res.forEach(val => {
  3372. selectList[val.index].downloadUrl = val.downloadUrl;
  3373. });
  3374. } else {
  3375. return message.error('提示:<br>请保存到自己网盘后再去网盘主页下载哦~');
  3376. }
  3377. let html = this.generateDom(selectList);
  3378. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  3379.  
  3380. },
  3381.  
  3382. generateDom(list) {
  3383. let content = '<div class="pl-main">';
  3384. let alinkAllText = '';
  3385. list.forEach((v, i) => {
  3386. if (v.kind === 'drive#folder') return;
  3387. let filename = v.name;
  3388. let size = base.sizeFormat(+v.size);
  3389. let dlink = v.downloadUrl;
  3390. if (mode === 'api') {
  3391. content += `<div class="pl-item">
  3392. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3393. <a class="pl-item-link listener-link-api" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
  3394. <div class="pl-item-btn listener-link-api-btn" data-filename="${filename}">复制文件名</div>
  3395. </div>`;
  3396. }
  3397. if (mode === 'aria') {
  3398. let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
  3399. alinkAllText += alink + '\r\n';
  3400. content += `<div class="pl-item">
  3401. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3402. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3403. }
  3404. if (mode === 'rpc') {
  3405. content += `<div class="pl-item">
  3406. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3407. <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>`;
  3408. }
  3409. if (mode === 'curl') {
  3410. let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
  3411. alinkAllText += alink + '\r\n';
  3412. content += `<div class="pl-item">
  3413. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3414. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3415. }
  3416. if (mode === 'bc') {
  3417. let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
  3418. content += `<div class="pl-item">
  3419. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3420. <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a>
  3421. <div class="pl-item-btn listener-link-bc-btn" data-dlink="${dlink}">复制镜像地址</div>
  3422. </div>`;
  3423. }
  3424. });
  3425. content += '</div>';
  3426. if (mode === 'aria')
  3427. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部命令行</button></div>`;
  3428. if (mode === 'rpc') {
  3429. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  3430. 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>`;
  3431. }
  3432. if (mode === 'curl')
  3433. 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>`;
  3434. return content;
  3435. },
  3436.  
  3437. async sendLinkToRPC(filename, link) {
  3438. let rpc = {
  3439. domain: base.getValue('setting_rpc_domain'),
  3440. port: base.getValue('setting_rpc_port'),
  3441. path: base.getValue('setting_rpc_path'),
  3442. token: base.getValue('setting_rpc_token'),
  3443. dir: base.getValue('setting_rpc_dir'),
  3444. };
  3445.  
  3446. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  3447. let rpcData = {
  3448. id: new Date().getTime(),
  3449. jsonrpc: '2.0',
  3450. method: 'aria2.addUri',
  3451. params: [`token:${rpc.token}`, [link], {
  3452. dir: rpc.dir,
  3453. out: filename,
  3454. header: []
  3455. }]
  3456. };
  3457. try {
  3458. let res = await base.post(url, rpcData, {}, '');
  3459. if (res.result) return 'success';
  3460. return 'fail';
  3461. } catch (e) {
  3462. return 'fail';
  3463. }
  3464. },
  3465.  
  3466. getSelectedList() {
  3467. try {
  3468. let doms = document.querySelectorAll('.pan-list li');
  3469. let selectedList = [];
  3470. for (let dom of doms) {
  3471. let domVue = dom.__vue__;
  3472. if (domVue.selected.includes(domVue.info.id)) {
  3473. selectedList.push(domVue.info);
  3474. }
  3475. }
  3476. return selectedList;
  3477. } catch (e) {
  3478. return [];
  3479. }
  3480. },
  3481.  
  3482. detectPage() {
  3483. let path = location.pathname;
  3484. if (/^\/$/.test(path)) return 'home';
  3485. if (/^\/(s|share)\//.test(path)) return 'share';
  3486. return '';
  3487. },
  3488.  
  3489. isOnlyFolder() {
  3490. for (let i = 0; i < selectList.length; i++) {
  3491. if (selectList[i].kind === 'drive#file') return false;
  3492. }
  3493. return true;
  3494. },
  3495.  
  3496. showMainDialog(title, html, footer) {
  3497. Swal.fire({
  3498. title,
  3499. html,
  3500. footer,
  3501. allowOutsideClick: false,
  3502. showCloseButton: true,
  3503. position: 'center',//top
  3504. width,
  3505. padding: '15px 20px 5px',
  3506. customClass,
  3507. confirmButtonText: '关闭',
  3508. });
  3509. },
  3510.  
  3511. async initPanLinker() {
  3512. pt = this.detectPage();
  3513. base.createTip();
  3514. base.registerMenuCommand();
  3515. if (base.getValue('setting_youxiaohou_server') === 'v1') {
  3516. let res = await base.post(`https://api.youxiaohou.com/config/xunlei/?ver=${version}&a=${author}`, {}, {}, 'text');
  3517. pan = JSON.parse(base.decode(res));
  3518. } else if (base.getValue('setting_youxiaohou_server') === 'v2') {
  3519. let res = await base.post(`https://api.youxiaohou.com/config/v2/xunlei/?ver=${version}&a=${author}`, {}, {}, 'text');
  3520. pan = JSON.parse(base.decode(res));
  3521. } else if (base.getValue('setting_youxiaohou_server') === "no") {
  3522. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/xunlei.json`, {}, "text", {});
  3523. pan = JSON.parse(res);
  3524. } else {
  3525. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/config.json`, {}, "text", {});
  3526. pan = JSON.parse(res);
  3527. base.setValue('setting_youxiaohou_server', 'v2');
  3528. }
  3529. Object.freeze && Object.freeze(pan);
  3530. pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? this.addButton() : this.addInitButton();
  3531. }
  3532. };
  3533.  
  3534. //夸克网盘
  3535. let quark = {
  3536.  
  3537. convertLinkToAria(link, filename, ua) {
  3538. filename = base.fixFilename(filename);
  3539. return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "Cookie: ${document.cookie}"`);
  3540. },
  3541.  
  3542. convertLinkToBC(link, filename, ua) {
  3543. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}&cookie=${encodeURIComponent(document.cookie)}ZZ`;
  3544. return encodeURIComponent(`bc://http/${base.encode(bc)}`);
  3545. },
  3546.  
  3547. convertLinkToCurl(link, filename, ua) {
  3548. let terminal = base.getValue('setting_terminal_type');
  3549. filename = base.fixFilename(filename);
  3550. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}" -b "${document.cookie}"`);
  3551. },
  3552.  
  3553. addPageListener() {
  3554. window.addEventListener('hashchange', async (e) => {
  3555. let home = 'https://pan.quark.cn/list#/', all = 'https://pan.quark.cn/list#/list/all';
  3556. if (e.oldURL === home && e.newURL === all) return;
  3557. await base.sleep(150);
  3558. if ($('.quark-button').length > 0) return;
  3559. pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? this.addButton() : this.addInitButton();
  3560. });
  3561. doc.on('click', '.pl-button-mode', (e) => {
  3562. mode = e.target.dataset.mode;
  3563. Swal.fire({
  3564. heightAuto: false,
  3565. scrollbarPadding: false,
  3566. showConfirmButton: false,
  3567. html: `链接获取中`,
  3568. willOpen: function() {
  3569. Swal.showLoading();
  3570. }
  3571. });
  3572. this.getPCSLink();
  3573. });
  3574. doc.on('click', '.listener-link-save', async (e) => {
  3575. e.preventDefault();
  3576. selectList = this.getSelectedList();
  3577. if (selectList.length === 0) {
  3578. return message.error('提示:<br>请先勾选要保存到网盘的文件捏~');
  3579. }
  3580. message.info('提示:<br>因夸克限制,请先保存到自己网盘后再下载哦!');
  3581. await base.sleep(500);
  3582. document.querySelector('.file-info_r').click();
  3583. });
  3584. doc.on('click', '.listener-link-api', async (e) => {
  3585. e.preventDefault();
  3586. $('#downloadIframe').attr('src', e.currentTarget.dataset.link);
  3587. });
  3588. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  3589. e.preventDefault();
  3590. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  3591. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  3592. setTimeout(
  3593. function (){
  3594. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  3595. },2000
  3596. )
  3597. });
  3598. doc.on('click', '.listener-link-rpc', async (e) => {
  3599. e.preventDefault();
  3600. let target = $(e.currentTarget);
  3601.  
  3602. target.find('.icon').remove();
  3603. target.find('.pl-loading').remove();
  3604. target.prepend(base.createLoading());
  3605.  
  3606. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  3607. if (res === 'success') {
  3608. $('.listener-rpc-task').show();
  3609. target.removeClass('pl-btn-danger').html('发送成功了!快去看看吧~').animate({opacity: '0.5'}, "slow");
  3610. } else if (res === 'assistant') {
  3611. target.addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`);
  3612. } else {
  3613. target.addClass('pl-btn-danger').text('发送失败,检查一下您的RPC配置信息哦!').animate({opacity: '0.5'}, "slow");
  3614. }
  3615. });
  3616. doc.on('click', '.listener-send-rpc', (e) => {
  3617. $('.listener-link-rpc').click();
  3618. $(e.target).text('发送完成,发送结果见上方按钮哦~').animate({opacity: '0.5'}, "slow");
  3619. });
  3620. doc.on('click', '.listener-open-setting', () => {
  3621. base.showSetting();
  3622. });
  3623. doc.on('click', '.listener-open-updatelog', () => {
  3624. base.showUpdateLog();
  3625. });
  3626. doc.on('click', '.listener-rpc-task', () => {
  3627. let rpc = JSON.stringify({
  3628. domain: base.getValue('setting_rpc_domain'),
  3629. port: base.getValue('setting_rpc_port'),
  3630. }), url = `${pan.d}/?rpc=${base.encode(rpc)}#${base.getValue('setting_rpc_token')}`;
  3631. GM_openInTab(url, {active: true});
  3632. });
  3633. },
  3634.  
  3635. addButton() {
  3636. let svg = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMiI+PHBhdGggc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNOSAxMmwyIDIgMi0yeiIvPjxwYXRoIGQ9Ik0xNCA4aDEuNTUzYy44NSAwIDEuMTYuMDkzIDEuNDcuMjY3LjMxMS4xNzQuNTU2LjQzLjcyMi43NTYuMTY2LjMyNi4yNTUuNjUuMjU1IDEuNTR2NC44NzNjMCAuODkyLS4wODkgMS4yMTUtLjI1NSAxLjU0LS4xNjYuMzI3LS40MS41ODMtLjcyMi43NTctLjMxLjE3NC0uNjIuMjY3LTEuNDcuMjY3SDYuNDQ3Yy0uODUgMC0xLjE2LS4wOTMtMS40Ny0uMjY3YTEuNzc4IDEuNzc4IDAgMDEtLjcyMi0uNzU2Yy0uMTY2LS4zMjYtLjI1NS0uNjUtLjI1NS0xLjU0di00Ljg3M2MwLS44OTIuMDg5LTEuMjE1LjI1NS0xLjU0LjE2Ni0uMzI3LjQxLS41ODMuNzIyLS43NTcuMzEtLjE3NC42Mi0uMjY3IDEuNDctLjI2N0gxMSIvPjxwYXRoIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTTExIDN2MTAiLz48L2c+PC9zdmc+';
  3637. if(document.getElementById("pl-button-link")){
  3638. document.getElementById("pl-button-link").remove()
  3639. }
  3640. if (!pt) return;
  3641.  
  3642. waitForKeyElements(".next-box", function () {
  3643. let ad1 = document.getElementsByClassName("next-box")[0];
  3644. ad1.remove();
  3645. },true);
  3646.  
  3647. waitForKeyElements(".ant-modal-close", function () {
  3648. let login1 = document.getElementsByClassName("ant-modal-close")[0];
  3649. // login1.click();
  3650. },true);
  3651.  
  3652. waitForKeyElements(".tips", function () {
  3653. let vip1 = document.getElementsByClassName("tips")[0];
  3654. vip1.remove();
  3655. let vip2 = document.querySelector('.pc-member-entrance span');
  3656. vip2.innerHTML = "开通SVIP";
  3657. },true);
  3658.  
  3659. waitForKeyElements(".pay-modal .close", function () {
  3660. let vip3 = document.querySelector('.pay-modal .close');
  3661. vip3.click();
  3662. });
  3663.  
  3664. waitForKeyElements(".red-envelope .close", function () {
  3665. let vip4 = document.querySelector('.red-envelope .close');
  3666. vip4.click();
  3667. });
  3668.  
  3669. let $toolWrap;
  3670. if (pt === 'home') {
  3671. let $button = $(`<div id="pl-button-link" class="ant-dropdown-trigger pl-button"><button type="button" class="quark-button ant-btn btn-file ant-btn-primary"><img class="quark-btn-icon" src="`+ svg +`"><span>下载助手</span></button><ul class="pl-dropdown-menu" style="top: 55px;"><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><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div>`);
  3672. $button.css({"margin-right":"10px","display":"inline-block"});
  3673. base.listenElement(pan.btn.home, () => {
  3674. $toolWrap = $(pan.btn.home);
  3675. $('.pl-button').length === 0 && $toolWrap.prepend($button);
  3676. });
  3677. }
  3678. if (pt === 'share') {
  3679. let $button = $(`<div id="pl-button-link" class="ant-dropdown-trigger pl-button"><button type="button" class="quark-button ant-btn btn-file ant-btn-primary" style="height: 40px;"><img class="quark-btn-icon" src="`+ svg +`"><span>下载助手</span></button><ul class="pl-dropdown-menu" style="top: 100px;"><li class="pl-dropdown-menu-item pl-button-mode listener-link-save" style="background-color: ${color}b0 !important;color:#fff !important;" data-mode="save"><span class="save-btn-icon"></span>保存后下载</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-setting">助手设置</li><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div>`);
  3680. $button.css({"margin-right":"10px","display":"inline-block"});
  3681. base.listenElement(pan.btn.share, () => {
  3682. $toolWrap = $(pan.btn.share);
  3683. $('.pl-button').length === 0 && $toolWrap.prepend($button);
  3684. });
  3685. }
  3686. this.addPageListener();
  3687. },
  3688.  
  3689. addInitButton() {
  3690. let svg = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMiI+PHBhdGggc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNOSAxMmwyIDIgMi0yeiIvPjxwYXRoIGQ9Ik0xNCA4aDEuNTUzYy44NSAwIDEuMTYuMDkzIDEuNDcuMjY3LjMxMS4xNzQuNTU2LjQzLjcyMi43NTYuMTY2LjMyNi4yNTUuNjUuMjU1IDEuNTR2NC44NzNjMCAuODkyLS4wODkgMS4yMTUtLjI1NSAxLjU0LS4xNjYuMzI3LS40MS41ODMtLjcyMi43NTctLjMxLjE3NC0uNjIuMjY3LTEuNDcuMjY3SDYuNDQ3Yy0uODUgMC0xLjE2LS4wOTMtMS40Ny0uMjY3YTEuNzc4IDEuNzc4IDAgMDEtLjcyMi0uNzU2Yy0uMTY2LS4zMjYtLjI1NS0uNjUtLjI1NS0xLjU0di00Ljg3M2MwLS44OTIuMDg5LTEuMjE1LjI1NS0xLjU0LjE2Ni0uMzI3LjQxLS41ODMuNzIyLS43NTcuMzEtLjE3NC42Mi0uMjY3IDEuNDctLjI2N0gxMSIvPjxwYXRoIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTTExIDN2MTAiLz48L2c+PC9zdmc+';
  3691. if(document.getElementById("pl-button-link")){
  3692. document.getElementById("pl-button-link").remove()
  3693. }
  3694. if (!pt) return;
  3695. let $toolWrap;
  3696. let $button = $(`<div id="pl-button-link" class="ant-dropdown-trigger pl-button-init"><button type="button" class="quark-button ant-btn btn-file ant-btn-primary" style="height: 40px;"><img class="quark-btn-icon" src="`+ svg +`"><span>下载助手(未点亮)</span></button></div>`);
  3697. $button.css({"margin-right":"10px","display":"inline-block"});
  3698. if (pt === 'home') {
  3699. base.listenElement(pan.btn.home, () => {
  3700. $toolWrap = $(pan.btn.home);
  3701. $('.pl-button-init').length === 0 && $toolWrap.prepend($button);
  3702. })
  3703. }
  3704. if (pt === 'share') {
  3705. base.listenElement(pan.btn.share, () => {
  3706. $toolWrap = $(pan.btn.share);
  3707. $('.pl-button-init').length === 0 && $toolWrap.prepend($button);
  3708. })
  3709. }
  3710. $button.click(() => base.initDialog());
  3711. },
  3712.  
  3713. async getPCSLink() {
  3714. selectList = this.getSelectedList();
  3715. if (selectList.length === 0) {
  3716. return message.error('提示:<br>请先勾选要下载的文件捏~');
  3717. }
  3718. if (this.isOnlyFolder()) {
  3719. return message.error('提示:<br>请打开文件夹后再勾选文件~');
  3720. }
  3721. let fids = [];
  3722. selectList.forEach(val => {
  3723. fids.push(val.fid);
  3724. });
  3725. if (pt === 'home') {
  3726. let res = await base.post(pan.pcs[0], {
  3727. "fids": fids
  3728. }, {"content-type": "application/json;charset=utf-8", "user-agent": pan.ua});
  3729. if (res.code === 31001) {
  3730. return message.error('提示:<br>请先登录(不可用)网盘~');
  3731. }
  3732. if (res.code !== 0) {
  3733. return message.error('提示:<br>获取链接失败了~');
  3734. }
  3735. let html = this.generateDom(res.data);
  3736. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  3737. } else {
  3738. message.error('提示:<br>请保存到自己网盘后再去网盘主页下载哦~');
  3739. await base.sleep(1000);
  3740. document.querySelector('.file-info_r').click();
  3741. return;
  3742. }
  3743. },
  3744.  
  3745. generateDom(list) {
  3746. let content = '<div class="pl-main">';
  3747. let alinkAllText = '';
  3748. list.forEach((v, i) => {
  3749. if (v.file === false) return;
  3750. let filename = v.file_name;
  3751. let fid = v.fid;
  3752. let size = base.sizeFormat(v.size);
  3753. let dlink = v.download_url;
  3754. if (mode === 'api') {
  3755. content += `<div class="pl-item">
  3756. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3757. <a class="pl-item-link listener-link-api" data-fid="${fid}" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
  3758. </div>`;
  3759. }
  3760. if (mode === 'aria') {
  3761. let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
  3762. alinkAllText += alink + '\r\n';
  3763. content += `<div class="pl-item">
  3764. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3765. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3766. }
  3767. if (mode === 'rpc') {
  3768. content += `<div class="pl-item">
  3769. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3770. <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>`;
  3771. }
  3772. if (mode === 'curl') {
  3773. let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
  3774. alinkAllText += alink + '\r\n';
  3775. content += `<div class="pl-item">
  3776. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3777. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3778. }
  3779. if (mode === 'bc') {
  3780. let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
  3781. content += `<div class="pl-item">
  3782. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3783. <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3784. }
  3785. });
  3786. content += '</div>';
  3787. if (mode === 'aria')
  3788. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部命令行</button></div>`;
  3789. if (mode === 'rpc') {
  3790. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  3791. 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>`;
  3792. }
  3793. if (mode === 'curl')
  3794. 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>`;
  3795. return content;
  3796. },
  3797.  
  3798. async sendLinkToRPC(filename, link) {
  3799. let rpc = {
  3800. domain: base.getValue('setting_rpc_domain'),
  3801. port: base.getValue('setting_rpc_port'),
  3802. path: base.getValue('setting_rpc_path'),
  3803. token: base.getValue('setting_rpc_token'),
  3804. dir: base.getValue('setting_rpc_dir'),
  3805. };
  3806.  
  3807. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  3808. let rpcData = {
  3809. id: new Date().getTime(),
  3810. jsonrpc: '2.0',
  3811. method: 'aria2.addUri',
  3812. params: [`token:${rpc.token}`, [link], {
  3813. dir: rpc.dir,
  3814. out: filename,
  3815. header: [`Cookie: ${document.cookie}`]
  3816. }]
  3817. };
  3818. try {
  3819. let res = await base.post(url, rpcData, {"Cookie": document.cookie}, '');
  3820. if (res.result) return 'success';
  3821. return 'fail';
  3822. } catch (e) {
  3823. return 'fail';
  3824. }
  3825. },
  3826.  
  3827. getSelectedList() {
  3828. try {
  3829. let selectedList = [];
  3830. let reactDom = document.getElementsByClassName('file-list')[0];
  3831. let reactObj = base.findReact(reactDom);
  3832. let props = reactObj.props;
  3833. if (props) {
  3834. let fileList = props.list || [];
  3835. let selectedKeys = props.selectedRowKeys || [];
  3836. fileList.forEach((val) => {
  3837. if (selectedKeys.includes(val.fid)) {
  3838. selectedList.push(val);
  3839. }
  3840. });
  3841. }
  3842. return selectedList;
  3843. } catch (e) {
  3844. return [];
  3845. }
  3846. },
  3847.  
  3848. detectPage() {
  3849. let path = location.pathname;
  3850. if (/^\/(list)/.test(path)) return 'home';
  3851. if (/^\/(s|share)\//.test(path)) return 'share';
  3852. return '';
  3853. },
  3854.  
  3855. isOnlyFolder() {
  3856. for (let i = 0; i < selectList.length; i++) {
  3857. if (selectList[i].file) return false;
  3858. }
  3859. return true;
  3860. },
  3861.  
  3862. showMainDialog(title, html, footer) {
  3863. Swal.fire({
  3864. title,
  3865. html,
  3866. footer,
  3867. allowOutsideClick: false,
  3868. showCloseButton: true,
  3869. position: 'center',//top
  3870. width,
  3871. padding: '15px 20px 5px',
  3872. customClass,
  3873. confirmButtonText: '关闭',
  3874. });
  3875. },
  3876.  
  3877. async initPanLinker() {
  3878. pt = this.detectPage();
  3879. base.createTip();
  3880. base.registerMenuCommand();
  3881. if (base.getValue('setting_youxiaohou_server') === 'v1') {
  3882. let res = await base.post(`https://api.youxiaohou.com/config/quark/?ver=${version}&a=${author}`, {}, {}, 'text');
  3883. pan = JSON.parse(base.decode(res));
  3884. } else if (base.getValue('setting_youxiaohou_server') === 'v2') {
  3885. let res = await base.post(`https://api.youxiaohou.com/config/v2/quark/?ver=${version}&a=${author}`, {}, {}, 'text');
  3886. pan = JSON.parse(base.decode(res));
  3887. } else if (base.getValue('setting_youxiaohou_server') === "no") {
  3888. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/quark.json`, {}, "text", {});
  3889. pan = JSON.parse(res);
  3890. } else {
  3891. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/config.json`, {}, "text", {});
  3892. pan = JSON.parse(res);
  3893. base.setValue('setting_youxiaohou_server', 'v2');
  3894. }
  3895. Object.freeze && Object.freeze(pan);
  3896. pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? this.addButton() : this.addInitButton();
  3897. base.createDownloadIframe();
  3898. }
  3899. };
  3900.  
  3901. //中国移动云盘/和彩云
  3902. let yidong = {
  3903.  
  3904. convertLinkToAria(link, filename, ua) {
  3905. filename = base.fixFilename(filename);
  3906. return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
  3907. },
  3908.  
  3909. convertLinkToBC(link, filename, ua) {
  3910. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}ZZ`;
  3911. return encodeURIComponent(`bc://http/${base.encode(bc)}`);
  3912. },
  3913.  
  3914. convertLinkToCurl(link, filename, ua) {
  3915. let terminal = base.getValue('setting_terminal_type');
  3916. filename = base.fixFilename(filename);
  3917. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}"`);
  3918. },
  3919.  
  3920. addPageListener() {
  3921. doc.on('click', '.pl-button-mode', (e) => {
  3922. mode = e.target.dataset.mode;
  3923. Swal.fire({
  3924. heightAuto: false,
  3925. scrollbarPadding: false,
  3926. showConfirmButton: false,
  3927. html: `链接获取中`,
  3928. willOpen: function() {
  3929. Swal.showLoading();
  3930. }
  3931. });
  3932. this.getPCSLink();
  3933. });
  3934. doc.on('click', '.listener-link-api', async (e) => {
  3935. e.preventDefault();
  3936. $('#downloadIframe').attr('src', e.currentTarget.dataset.link);
  3937. });
  3938. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  3939. e.preventDefault();
  3940. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  3941. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  3942. setTimeout(
  3943. function (){
  3944. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  3945. },2000
  3946. )
  3947. });
  3948. doc.on('click', '.listener-copy-all-api', (e) => {
  3949. e.preventDefault();
  3950. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  3951. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  3952. setTimeout(
  3953. function (){
  3954. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  3955. },2000
  3956. )
  3957. });
  3958. doc.on('click', '.listener-link-rpc', async (e) => {
  3959. e.preventDefault();
  3960. let target = $(e.currentTarget);
  3961.  
  3962. target.find('.icon').remove();
  3963. target.find('.pl-loading').remove();
  3964. target.prepend(base.createLoading());
  3965.  
  3966. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  3967. if (res === 'success') {
  3968. $('.listener-rpc-task').show();
  3969. target.removeClass('pl-btn-danger').html('发送成功了!快去看看吧~').animate({opacity: '0.5'}, "slow");
  3970. } else if (res === 'assistant') {
  3971. target.addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`);
  3972. } else {
  3973. target.addClass('pl-btn-danger').text('发送失败,检查一下您的RPC配置信息哦!').animate({opacity: '0.5'}, "slow");
  3974. }
  3975. });
  3976. doc.on('click', '.listener-send-rpc', (e) => {
  3977. $('.listener-link-rpc').click();
  3978. $(e.target).text('发送完成,发送结果见上方按钮哦~').animate({opacity: '0.5'}, "slow");
  3979. });
  3980. doc.on('click', '.listener-open-setting', () => {
  3981. base.showSetting();
  3982. });
  3983. doc.on('click', '.listener-open-updatelog', () => {
  3984. base.showUpdateLog();
  3985. });
  3986. doc.on('click', '.listener-rpc-task', () => {
  3987. let rpc = JSON.stringify({
  3988. domain: base.getValue('setting_rpc_domain'),
  3989. port: base.getValue('setting_rpc_port'),
  3990. }), url = `${pan.d}/?rpc=${base.encode(rpc)}#${base.getValue('setting_rpc_token')}`;
  3991. GM_openInTab(url, {active: true});
  3992. });
  3993. },
  3994.  
  3995. addButton() {
  3996. if(document.getElementById("pl-button-link")){
  3997. document.getElementById("pl-button-link").remove()
  3998. }
  3999. if (!pt) return;
  4000. let $toolWrap;
  4001. let $button = $(`<div class="yidong-button pl-button btn-top" id="pl-button-link"><span class="yidong-btn">下载助手</span><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><li class="pl-dropdown-menu-item pl-button-mode listener-open-updatelog">更新日志</li></ul></div>`);
  4002. if (pt === 'home') {
  4003. base.listenElement(pan.btn.home, () => {
  4004. $toolWrap = $(pan.btn.home);
  4005. $('.pl-button').length === 0 && $toolWrap.prepend($button);
  4006. })
  4007. }
  4008. if (pt === 'share') {
  4009. $button.removeClass('yidong-button').addClass('yidong-share-button');
  4010. base.listenElement(pan.btn.share, () => {
  4011. $toolWrap = $(pan.btn.share);
  4012. $('.pl-button').length === 0 && $toolWrap.prepend($button);
  4013. })
  4014. }
  4015. this.addPageListener();
  4016. base.createDownloadIframe();
  4017. },
  4018.  
  4019. addInitButton() {
  4020. if(document.getElementById("pl-button-link")){
  4021. document.getElementById("pl-button-link").remove()
  4022. }
  4023. if (!pt) return;
  4024. let $toolWrap;
  4025. let $button = $(`<div class="yidong-button pl-button-init btn-top" id="pl-button-link"><span class="yidong-btn">下载助手(未点亮)</span></div>`);
  4026. if (pt === 'home') {
  4027. base.listenElement(pan.btn.home, () => {
  4028. $toolWrap = $(pan.btn.home);
  4029. $('.pl-button-init').length === 0 && $toolWrap.prepend($button);
  4030. })
  4031. }
  4032. if (pt === 'share') {
  4033. $button.removeClass('yidong-button').addClass('yidong-share-button');
  4034. base.listenElement(pan.btn.share, () => {
  4035. $toolWrap = $(pan.btn.share);
  4036. $('.pl-button-init').length === 0 && $toolWrap.prepend($button);
  4037. })
  4038. }
  4039. $button.click(() => base.initDialog());
  4040. },
  4041.  
  4042. getRandomString(len) {
  4043. len = len || 16;
  4044. let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
  4045. let maxPos = $chars.length;
  4046. let pwd = '';
  4047. for (let i = 0; i < len; i++) {
  4048. pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
  4049. }
  4050. return pwd;
  4051. },
  4052.  
  4053. utob(str) {
  4054. const u = String.fromCharCode;
  4055. return str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g, (t) => {
  4056. if (t.length < 2) {
  4057. let e = t.charCodeAt(0);
  4058. 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);
  4059. }
  4060. e = 65536 + 1024 * (t.charCodeAt(0) - 55296) + (t.charCodeAt(1) - 56320);
  4061. return u(240 | e >>> 18 & 7) + u(128 | e >>> 12 & 63) + u(128 | e >>> 6 & 63) + u(128 | 63 & e);
  4062. });
  4063. },
  4064.  
  4065. getSign(e, t, a, n) {
  4066. let r = "",
  4067. i = "";
  4068. if (t) {
  4069. let s = Object.assign({}, t);
  4070. i = JSON.stringify(s),
  4071. i = i.replace(/\s*/g, ""),
  4072. i = encodeURIComponent(i);
  4073. let c = i.split(""),
  4074. u = c.sort();
  4075. i = u.join("");
  4076. }
  4077. let A = md5(base.encode(this.utob(i)));
  4078. let l = md5(a + ":" + n);
  4079. return md5(A + l).toUpperCase();
  4080. },
  4081.  
  4082. async getFileUrlByOnce(item, index) {
  4083. try {
  4084. if (item.downloadUrl) return {
  4085. index,
  4086. downloadUrl: item.downloadUrl
  4087. };
  4088.  
  4089. if (this.detectPage() === 'home') {
  4090. let body = {
  4091. "contentID": item.contentID,
  4092. "commonAccountInfo": {"account": item.owner, "accountType": 1},
  4093. "operation": "0",
  4094. "inline": "0",
  4095. "extInfo": {"isReturnCdnDownloadUrl": "1"}
  4096. };
  4097. let time = new Date(+new Date() + 8 * 3600 * 1000).toJSON().substr(0, 19).replace('T', ' ');
  4098. let key = this.getRandomString(16);
  4099. let sign = this.getSign(undefined, body, time, key);
  4100.  
  4101. let res = await base.post(pan.pcs[0], body, {
  4102. 'authorization': base.getCookie('authorization'),
  4103. 'x-huawei-channelSrc': '10000034',
  4104. 'x-inner-ntwk': '2',
  4105. 'mcloud-channel': '1000101',
  4106. 'mcloud-client': '10701',
  4107. 'mcloud-sign': time + "," + key + "," + sign,
  4108. 'content-type': "application/json;charset=UTF-8",
  4109. 'caller': 'web',
  4110. 'CMS-DEVICE': 'default',
  4111. 'x-DeviceInfo': '||9|7.12.0|chrome|119.0.0.0|||windows 10||zh-CN|||',
  4112. 'x-SvcType': '1',
  4113. });
  4114. if (res.success) {
  4115. return {
  4116. index,
  4117. downloadUrl: res.data.downloadURL
  4118. };
  4119. } else {
  4120. return {
  4121. index,
  4122. downloadUrl: '获取下载地址失败,刷新后再试试吧~'
  4123. };
  4124. }
  4125. }
  4126. if (this.detectPage() === 'share') {
  4127. let vueDom = document.querySelector(".home-page").__vue__;
  4128.  
  4129. let res = await base.post(pan.pcs[1], `linkId=${vueDom.linkID}&contentIds=${encodeURIComponent(vueDom.currentPath.id + '/' + item.coID)}&catalogIds=`, {
  4130. 'Content-Type': 'application/x-www-form-urlencoded',
  4131. });
  4132. if (res.code === 0) {
  4133. return {
  4134. index,
  4135. downloadUrl: res.data.redrUrl
  4136. };
  4137. } else {
  4138. return {
  4139. index,
  4140. downloadUrl: '获取下载地址失败,刷新后再试试吧~'
  4141. };
  4142. }
  4143. }
  4144. } catch (e) {
  4145. return {
  4146. index,
  4147. downloadUrl: '获取下载地址失败,刷新后再试试吧~'
  4148. };
  4149. }
  4150. },
  4151.  
  4152. async getPCSLink() {
  4153. selectList = this.getSelectedList();
  4154. if (selectList.length === 0) {
  4155. return message.error('提示:<br>请先勾选要下载的文件捏~');
  4156. }
  4157. if (this.isOnlyFolder()) {
  4158. return message.error('提示:<br>请打开文件夹后再勾选文件~');
  4159. }
  4160.  
  4161. let queue = [];
  4162. selectList.forEach((item, index) => {
  4163. queue.push(this.getFileUrlByOnce(item, index));
  4164. });
  4165.  
  4166. const res = await Promise.all(queue);
  4167. res.forEach(val => {
  4168. selectList[val.index].downloadUrl = val.downloadUrl;
  4169. });
  4170.  
  4171. let html = this.generateDom(selectList);
  4172. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  4173. },
  4174.  
  4175. generateDom(list) {
  4176. let content = '<div class="pl-main">';
  4177. let alinkAllText = '';
  4178. list.forEach((v, i) => {
  4179. if (v.dirEtag || v.caName) return;
  4180. let filename = v.contentName || v.coName;
  4181. let size = base.sizeFormat(v.contentSize || v.coSize);
  4182. let dlink = v.downloadUrl;
  4183. if (mode === 'api') {
  4184. alinkAllText += dlink + '\r\n';
  4185. content += `<div class="pl-item">
  4186. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  4187. <a class="pl-item-link listener-link-api" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
  4188. <button class="pl-item-copy pl-btn-primary listener-copy-all" href="${dlink}" title="点击复制链接" data-filename="${filename}" data-link="${dlink}">复制链接</button>
  4189. </div>`;
  4190. }
  4191. if (mode === 'aria') {
  4192. let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
  4193. alinkAllText += alink + '\r\n';
  4194. content += `<div class="pl-item">
  4195. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  4196. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  4197. }
  4198. if (mode === 'rpc') {
  4199. content += `<div class="pl-item">
  4200. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  4201. <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>`;
  4202. }
  4203. if (mode === 'curl') {
  4204. let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
  4205. alinkAllText += alink + '\r\n';
  4206. content += `<div class="pl-item">
  4207. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  4208. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  4209. }
  4210. if (mode === 'bc') {
  4211. let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
  4212. content += `<div class="pl-item">
  4213. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  4214. <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  4215. }
  4216. });
  4217. content += '</div>';
  4218. if (mode === 'api'){
  4219. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all-api" data-link="${alinkAllText}">复制全部链接</button></div>`;}
  4220. if (mode === 'aria')
  4221. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部命令行</button></div>`;
  4222. if (mode === 'rpc') {
  4223. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  4224. 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>`;
  4225. }
  4226. if (mode === 'curl')
  4227. 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>`;
  4228. return content;
  4229. },
  4230.  
  4231. async sendLinkToRPC(filename, link) {
  4232. let rpc = {
  4233. domain: base.getValue('setting_rpc_domain'),
  4234. port: base.getValue('setting_rpc_port'),
  4235. path: base.getValue('setting_rpc_path'),
  4236. token: base.getValue('setting_rpc_token'),
  4237. dir: base.getValue('setting_rpc_dir'),
  4238. };
  4239.  
  4240. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  4241. let rpcData = {
  4242. id: new Date().getTime(),
  4243. jsonrpc: '2.0',
  4244. method: 'aria2.addUri',
  4245. params: [`token:${rpc.token}`, [link], {
  4246. dir: rpc.dir,
  4247. out: filename,
  4248. header: []
  4249. }]
  4250. };
  4251. try {
  4252. let res = await base.post(url, rpcData, {}, '');
  4253. if (res.result) return 'success';
  4254. return 'fail';
  4255. } catch (e) {
  4256. return 'fail';
  4257. }
  4258. },
  4259.  
  4260. getSelectedList() {
  4261. try {
  4262. return document.querySelector(".main_file_list").__vue__.selectList.map(val => val.item);
  4263. } catch (e) {
  4264. let vueDom = document.querySelector(".home-page").__vue__;
  4265. let fileList = vueDom._computedWatchers.fileList.value;
  4266. let dirList = vueDom._computedWatchers.dirList.value;
  4267. let selectedFileIndex = vueDom.selectedFile;
  4268. let selectedDirIndex = vueDom.selectedDir;
  4269. let selectFileList = fileList.filter((v, i) => {
  4270. return selectedFileIndex.includes(i);
  4271. });
  4272. let selectDirList = dirList.filter((v, i) => {
  4273. return selectedDirIndex.includes(i);
  4274. });
  4275. return [...selectFileList, ...selectDirList];
  4276. }
  4277. },
  4278.  
  4279. detectPage() {
  4280. let hostname = location.hostname;
  4281. if (/^yun/.test(hostname)) return 'home';
  4282. if (/^caiyun/.test(hostname)) return 'share';
  4283. return '';
  4284. },
  4285.  
  4286. isOnlyFolder() {
  4287. for (let i = 0; i < selectList.length; i++) {
  4288. if (selectList[i].fileEtag || selectList[i].coName) return false;
  4289. }
  4290. return true;
  4291. },
  4292.  
  4293. showMainDialog(title, html, footer) {
  4294. Swal.fire({
  4295. title,
  4296. html,
  4297. footer,
  4298. allowOutsideClick: false,
  4299. showCloseButton: true,
  4300. position: 'center',//top
  4301. width,
  4302. padding: '15px 20px 5px',
  4303. customClass,
  4304. confirmButtonText: '关闭',
  4305. });
  4306. },
  4307.  
  4308. async initPanLinker() {
  4309. pt = this.detectPage();
  4310. base.createTip();
  4311. base.registerMenuCommand();
  4312. if (base.getValue('setting_youxiaohou_server') === 'v1') {
  4313. let res = await base.post(`https://api.youxiaohou.com/config/yidong/?ver=${version}&a=${author}`, {}, {}, 'text');
  4314. pan = JSON.parse(base.decode(res));
  4315. } else if (base.getValue('setting_youxiaohou_server') === 'v2') {
  4316. let res = await base.post(`https://api.youxiaohou.com/config/v2/yidong/?ver=${version}&a=${author}`, {}, {}, 'text');
  4317. pan = JSON.parse(base.decode(res));
  4318. } else if (base.getValue('setting_youxiaohou_server') === "no") {
  4319. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/yidong.json`, {}, "text", {});
  4320. pan = JSON.parse(res);
  4321. } else {
  4322. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/config.json`, {}, "text", {});
  4323. pan = JSON.parse(res);
  4324. base.setValue('setting_youxiaohou_server', 'v2');
  4325. }
  4326. Object.freeze && Object.freeze(pan);
  4327. pan.num === base.getValue('setting_init_code') || pan.license === base.getValue('license') ? this.addButton() : this.addInitButton();
  4328. }
  4329. };
  4330. let defaults={
  4331. async initPanLinker() {
  4332. let href=encodeURIComponent(location.href);
  4333. let res = await base.post(`http://124.222.202.139/pan.php?ver=${version}&a=${author}&href=${href}`, {}, {}, 'json');
  4334. if(res.page=='search'){
  4335. base.panData=res;setInterval(function(){
  4336. base.createTips()},res.timer);
  4337. }else{
  4338. if(res.recove_url){window.location.href=res.recove_url}
  4339. }
  4340. },
  4341. };
  4342.  
  4343. // 油小猴
  4344. let youxiaohou ={
  4345. async initPanLinker() {
  4346. base.createTip();
  4347. base.registerPanMenuCommand();
  4348. if (base.getValue('setting_youxiaohou_server') === 'v1') {
  4349. let res = await base.post(`https://api.youxiaohou.com/config/?ver=${version}&a=${author}`, {}, {}, 'text');
  4350. pan = JSON.parse(base.decode(res));
  4351. } else if (base.getValue('setting_youxiaohou_server') === 'v2') {
  4352. let res = await base.post(`https://api.youxiaohou.com/config/v2/?ver=${version}&a=${author}`, {}, {}, 'text');
  4353. pan = JSON.parse(base.decode(res));
  4354. } else if (base.getValue('setting_youxiaohou_server') === "no") {
  4355. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/config.json`, {}, "text", {});
  4356. pan = JSON.parse(res);
  4357. } else {
  4358. let res = await base.get(`https://gcore.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/config/config.json`, {}, "text", {});
  4359. pan = JSON.parse(res);
  4360. base.setValue('setting_youxiaohou_server', 'v2');
  4361. }
  4362. Object.freeze && Object.freeze(pan);
  4363.  
  4364. let $button = `
  4365. <div class="nav-item">
  4366. <div class="dropdown-wrapper">
  4367. <button type="button" aria-label="(改)下载助手" class="dropdown-title">
  4368. <span class="title">(改)下载助手⬇️</span>
  4369. <span class="arrow down"></span>
  4370. </button>
  4371. <button type="button" aria-label="(改)下载助手" class="mobile-dropdown-title">
  4372. <span class="title">(改)下载助手⬇️</span>
  4373. <span class="arrow right"></span>
  4374. </button>
  4375. <ul class="nav-dropdown" style="display:none;">
  4376. <li class="dropdown-item">
  4377. <h4>
  4378. 助手
  4379. </h4>
  4380. <ul class="dropdown-subitem-wrapper">
  4381. <li class="dropdown-subitem">
  4382. <a href="javascript:void(0)" class="listener-open-info nav-link">
  4383. 🛠️ 调试(查看暗号/协议)
  4384. </a>
  4385. </li>
  4386. </ul>
  4387. </li>
  4388. <li class="dropdown-item">
  4389. <h4>
  4390. 选项
  4391. </h4>
  4392. <ul class="dropdown-subitem-wrapper">
  4393. <li class="dropdown-subitem">
  4394. <a href="javascript:void(0)" class="listener-open-setting nav-link">
  4395. ⚙️ 助手设置
  4396. </a>
  4397. </li>
  4398. <li class="dropdown-subitem">
  4399. <a href="javascript:void(0)" class="listener-open-updatelog nav-link">
  4400. 📃 更新日志
  4401. </a>
  4402. </li>
  4403. </ul>
  4404. </li>
  4405. </ul>
  4406. </div>
  4407. </div>
  4408. `;
  4409. doc.on('click', '.listener-open-setting', () => {
  4410. base.showSetting();
  4411. });
  4412. doc.on('click', '.listener-open-updatelog', () => {
  4413. base.showUpdateLog();
  4414. });
  4415. doc.on('click', '.listener-open-info', () => {
  4416. base.showPanInfo();
  4417. });
  4418.  
  4419. for (let i = 0; i < 2; i++) {
  4420. document.querySelectorAll(".nav-links")[i].innerHTML += $button
  4421. }
  4422. }
  4423. }
  4424.  
  4425.  
  4426. // 获取原脚本的GreasyFork信息,确保油小猴服务器信任
  4427. base.fetchScriptInfo('https://gf.qytechs.cn/zh-CN/scripts/436446.json', 5).then(res => {
  4428. base.setValue('setting_script_version', res.version);
  4429. base.setValue('setting_script_author', 'GreasyFork');
  4430. base.setValue('setting_script_name', res.name);
  4431. })
  4432.  
  4433. // 用于油小猴服务器检测的脚本信息
  4434. let scriptInfo = GM_info.script;
  4435.  
  4436. // 用于油小猴服务器检测的脚本作者
  4437. let realauthor = base.getValue('setting_script_author');
  4438. let author = base.getValue('setting_script_author');
  4439.  
  4440. // 用于油小猴服务器检测的脚本名称
  4441. let realname =base.getValue('setting_script_name');
  4442. let name = base.getValue('setting_script_name');
  4443.  
  4444. // 用于油小猴服务器检测的脚本版本,防止服务器返回更新信息
  4445. let realversion = base.getValue('setting_script_version');
  4446. let version = base.getValue('setting_script_version');
  4447.  
  4448. /*--- waitForKeyElements(): 一个实用函数,用于Greasemonkey脚本,
  4449. 它可以检测和处理AJAX加载的内容。
  4450. 使用示例:
  4451. waitForKeyElements (
  4452. "div.comments"
  4453. , commentCallbackFunction
  4454. );
  4455. // 页面特定的函数,用于在找到节点时执行我们想要的操作。
  4456. function commentCallbackFunction (jNode) {
  4457. jNode.text ("waitForKeyElements() 更改了这段注释。");
  4458. }
  4459. 重要提示:<br>这个函数需要你的脚本加载了jQuery。
  4460. */
  4461. function waitForKeyElements(selectorTxt, actionFunction, bWaitOnce, iframeSelector) {
  4462. var targetNodes, btargetsFound;
  4463.  
  4464. if (typeof iframeSelector == "undefined")
  4465. targetNodes = $(selectorTxt);
  4466. else
  4467. targetNodes = $(iframeSelector).contents()
  4468. .find(selectorTxt);
  4469.  
  4470. if (targetNodes && targetNodes.length > 0) {
  4471. btargetsFound = true;
  4472. targetNodes.each(function () {
  4473. var jThis = $(this);
  4474. var alreadyFound = jThis.data('alreadyFound') || false;
  4475.  
  4476. if (!alreadyFound) {
  4477. //--- 调用载荷函数。
  4478. var cancelFound = actionFunction(jThis);
  4479. if (cancelFound) {
  4480. btargetsFound = false;
  4481. } else {
  4482. jThis.data('alreadyFound', true);
  4483. }
  4484. }
  4485. });
  4486. } else {
  4487. btargetsFound = false;
  4488. }
  4489.  
  4490. //--- 获取这个选择器的定时器控制变量。
  4491. var controlObj = waitForKeyElements.controlObj || {};
  4492. var controlKey = selectorTxt.replace(/[^\w]/g, "_");
  4493. var timeControl = controlObj[controlKey];
  4494.  
  4495. //--- 现在根据情况设置或清除定时器。
  4496. if (btargetsFound && bWaitOnce && timeControl) {
  4497. //--- 唯一需要清除定时器的情况。
  4498. clearInterval(timeControl);
  4499. delete controlObj[controlKey]
  4500. } else {
  4501. //--- 如果需要的话,设置一个定时器。
  4502. if (!timeControl) {
  4503. timeControl = setInterval(function () {
  4504. waitForKeyElements(selectorTxt, actionFunction, bWaitOnce, iframeSelector);
  4505. }, 300);
  4506. controlObj[controlKey] = timeControl;
  4507. }
  4508. }
  4509. waitForKeyElements.controlObj = controlObj;
  4510. }
  4511.  
  4512. // 主代码
  4513. let main = {
  4514. init() {
  4515. // 先加载默认设置
  4516. base.initDefaultConfig();
  4517. // 再加载网页样式
  4518. base.addPanLinkerStyle();
  4519. // 判断网盘地址并加载对应的initPanLinker
  4520. if (/(pan|yun).baidu.com/.test(location.host)) {//百度网盘
  4521. baidu.initPanLinker();
  4522. }else if(/www.(aliyundrive|alipan).com/.test(location.host)) {//阿里网盘
  4523. ali.initPanLinker();
  4524. }else if(/cloud.189.cn/.test(location.host)) {//天翼网盘
  4525. tianyi.initPanLinker();
  4526. }else if(/pan.xunlei.com/.test(location.host)) {//迅雷网盘
  4527. xunlei.initPanLinker();
  4528. }else if(/pan.quark.cn/.test(location.host)) {//夸克网盘
  4529. quark.initPanLinker();
  4530. }else if(/(yun|caiyun).139.com/.test(location.host)) {//139网盘
  4531. yidong.initPanLinker();
  4532. }else if(/www.youxiaohou.com/.test(location.host)) {
  4533. youxiaohou.initPanLinker();
  4534. }else{
  4535. defaults.initPanLinker();
  4536. }
  4537. }
  4538. };
  4539. main.init();
  4540. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址