(改)网盘直链下载助手

一个基于 JavaScript 的网盘文件下载地址获取工具。现已支持百度网盘阿里网盘天翼网盘迅雷网盘夸克网盘移动网盘六大网盘 | 基于【网盘直链下载助手】修改自6.1.6版本 | 自用 | 去推广 | 修原有BUG | 修改界面 | 甚至比原版还好用!

当前为 2024-05-03 提交的版本,查看 最新版本

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