(改)网盘直链下载助手

一个基于 JavaScript 的网盘文件下载地址获取工具,支持 百度/阿里/天翼/迅雷/夸克/移动 六大网盘 | 基于【网盘直链下载助手】修改自6.1.6版本 | 开源 - 自用 - 去广 | 改界面 - 添功能 - 修Bug | 不仅能够精简网盘界面 还支持修改网盘界面主题颜色!

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

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