(改)网盘直链下载助手

可以获取网盘文件真实下载地址。现已支持百度阿里天翼迅雷夸克移动六大网盘,基于【网盘直链下载助手】修改自6.0.4版本,自用,去推广,修原有BUG,修改界面,比原版还好用!

当前为 2023-05-06 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name (改)网盘直链下载助手
  3. // @namespace https://github.com/syhyz1990/baiduyun
  4. // @version 1.0.6.1
  5. // @author Hmjz100、油小猴
  6. // @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij48cGF0aCBkPSJNMTAzLjYgMTA3LjRjMy41LTIuMiA4LjktNi4xIDEzLjgtMTIuNXM3LjMtMTIuNSA4LjUtMTYuNWMuNS0xLjcgMi4yLTcuNSAyLjItMTQuNyAwLTEwLjEtMy4zLTI1LjEtMTUuNC0zNi44LTE0LjUtMTQtMzIuMS0xNC4zLTM1LjctMTQuMy04IDAtMTUuNyAxLjktMjIuNiA1LjJDNDQgMjMgMzUuNyAzMS40IDMwLjggNDEuN2MtMS4zIDIuOC00IDQuNy03LjEgNS00IC4zLTcuNSA0LjQtOC45IDkuNi0uNSAxLjktMS42IDMuNS0zLjEgNC43QzQuNCA2Ni44IDAgNzUuNyAwIDg1YzAgNi44IDIuMyAxMy4xIDYuMSAxOC4yIDUuNSA3LjQgMTQuMiAxMi4yIDI0IDEyLjJoNDcuMWM0LjQgMCAxMS0uNSAxOC4zLTMuNSAzLjItMS40IDUuOS0zIDguMS00LjV6IiBmaWxsPSIjNDQ0Ii8+PHBhdGggZD0iTTExOS44IDY0LjNjLjEtMTcuMS0xMC40LTI4LTEyLjUtMzAuMUM5NSAyMi4xIDc5LjkgMjEuOCA3Ni45IDIxLjhjLTE3LjYgMC0zMy4zIDEwLjUtMzkuOSAyNi43LS42IDEuMy0xLjggMi4zLTMuNCAyLjNoLS40Yy01LjggMC0xMC42IDQuOC0xMC42IDEwLjd2LjVjMCAxLjQtLjggMi42LTEuOSAzLjNDMTMuNCA2OSA4LjggNzYuOCA4LjggODVjMCAxMi4yIDkuOSAyMi4zIDIyLjIgMjIuM2g0NS4yYzMuNi0uMSAxNy42LS45IDI5LjYtMTIgMi45LTIuOCAxMy45LTEzLjcgMTQtMzF6IiBmaWxsPSIjMTM5N2Q4Ii8+PHBhdGggZD0iTTExMC44IDU3LjRsLjIgMy4zYzAgMS4zLTEuMSAyLjQtMi4zIDIuNC0xLjMgMC0yLjMtMS4xLTIuMy0yLjRsLS4xLTIuOHYtLjNjMC0xLjIuOS0yLjIgMi4xLTIuM2guM2MuNyAwIDEuMy4zIDEuNy43LS4yLjEuMy41LjQgMS40em0tMy4zLTEwLjNjMCAxLjItMSAyLjMtMi4yIDIuM2gtLjFjLS44IDAtMS42LS41LTItMS4yLTQuNi04LjMtMTMuMy0xMy41LTIyLjgtMTMuNS0xLjIgMC0yLjMtMS0yLjMtMi4ydi0uMWMwLTEuMiAxLTIuMyAyLjItMi4zaC4xYTMwLjM3IDMwLjM3IDAgMCAxIDE1LjggNC40YzQuNiAyLjggOC40IDYuOCAxMS4xIDExLjUuMS4zLjIuNy4yIDEuMXpNODguMyA3My44TDczLjUgOTMuMmMtMS41IDEuOS0zLjUgMy4xLTUuNyAzLjVoLS4yYy0uNC4xLS44LjEtMS4yLjEtLjYgMC0xLjEtLjEtMS42LS4yLTIuMi0uNC00LjItMS43LTUuNi0zLjVMNDQuMyA3My45Yy0yLTIuNi0yLjUtNS40LTEuNC03LjcuMS0uMS4xLS4yLjItLjIgMS4yLTIgMy41LTMuMiA2LjQtMy4yaDYuNnYtNS43YzAtNi44IDQuNy0xMiAxMC45LTEyIDQuOCAwIDguNSAyLjYgMTAuMyA3LjIuNSAxLjMtLjIgMi43LTEuNSAzLjJzLTIuOC0uMS0zLjMtMS40Yy0xLjEtMi43LTIuOS00LTUuNS00LTMuNSAwLTYgMy02IDd2OC4xYzAgLjUtLjIgMS0uNiAxLjQtLjYuNy0xLjcgMS4xLTIuNiAxLjFoLTguNGMtMS4zIDAtMiAuNC0yLjEuNy0uMi40IDAgMS4zLjkgMi40TDYzLjEgOTBjLjkgMS4yIDIuMSAxLjggMy4zIDEuOHMyLjMtLjYgMy4xLTEuN2wxNC44LTE5LjNjLjktMS4xIDEuMS0yIC45LTIuNC0uMi0uMy0uOS0uNy0yLjEtLjdoLTcuNmMtLjkgMC0xLjctLjUtMi4xLTEuMi0uMy0uNC0uNC0uOC0uNC0xLjMgMC0xLjQgMS4xLTIuNSAyLjUtMi41aDcuNmMzLjEgMCA1LjUgMS4zIDYuNiAzLjVsLjMuN2MuNyAyLjEuMSA0LjYtMS43IDYuOXoiIGZpbGw9IiM0NDQiLz48L3N2Zz4=
  7. // @description 可以获取网盘文件真实下载地址。现已支持百度阿里天翼迅雷夸克移动六大网盘,基于【网盘直链下载助手】修改自6.0.4版本,自用,去推广,修原有BUG,修改界面,比原版还好用!
  8. // @license MIT
  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. // @match *://pan.baidu.com/disk/home*
  12. // @match *://yun.baidu.com/disk/home*
  13. // @match *://pan.baidu.com/disk/main*
  14. // @match *://yun.baidu.com/disk/main*
  15. // @match *://pan.baidu.com/s/*
  16. // @match *://yun.baidu.com/s/*
  17. // @match *://pan.baidu.com/share/*
  18. // @match *://yun.baidu.com/share/*
  19. // @match *://www.aliyundrive.com/s/*
  20. // @match *://www.aliyundrive.com/drive*
  21. // @match *://cloud.189.cn/web/*
  22. // @match *://pan.xunlei.com/*
  23. // @match *://pan.quark.cn/*
  24. // @match *://yun.139.com/*
  25. // @match *://caiyun.139.com/*
  26. // @match *://*.youxiaohou.com/*
  27. // @require https://unpkg.com/jquery@3.6.0/dist/jquery.min.js
  28. // @require https://fastly.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js
  29. // @require https://unpkg.com/js-md5@0.7.3/build/md5.min.js
  30. // @resource AlertCSS https://fastly.jsdelivr.net/gh/hmjz100/Online-disk-direct-link-download-assistant@main/default.min.css
  31. // @connect baidu.com
  32. // @connect baidupcs.com
  33. // @connect aliyundrive.com
  34. // @connect 189.cn
  35. // @connect xunlei.com
  36. // @connect quark.cn
  37. // @connect youxiaohou.com
  38. // @connect localhost
  39. // @connect *
  40. // @run-at document-idle
  41. // @compatible Chrome
  42. // @compatible Firefox
  43. // @compatible Safari
  44. // @compatible Edge
  45. // @compatible Opera
  46. // @grant unsafeWindow
  47. // @grant GM_xmlhttpRequest
  48. // @grant GM_setClipboard
  49. // @grant GM_setValue
  50. // @grant GM_getValue
  51. // @grant GM_openInTab
  52. // @grant GM_info
  53. // @grant GM_registerMenuCommand
  54. // @grant GM_cookie
  55. // @grant GM_addStyle
  56. // @grant GM_getResourceText
  57. // ==/UserScript==
  58.  
  59. (function () {
  60. 'use strict';
  61. function generateRandomNumberInRange(min, max) {
  62. return Math.floor(Math.random() * (max - min + 1) + min);
  63. };
  64. /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts,
  65. that detects and handles AJAXed content.
  66. Usage example:
  67. waitForKeyElements (
  68. "div.comments"
  69. , commentCallbackFunction
  70. );
  71. //--- Page-specific function to do what we want when the node is found.
  72. function commentCallbackFunction (jNode) {
  73. jNode.text ("This comment changed by waitForKeyElements().");
  74. }
  75. IMPORTANT: This function requires your script to have loaded jQuery.
  76. */
  77. function waitForKeyElements(selectorTxt, actionFunction, bWaitOnce, iframeSelector) {
  78. var targetNodes, btargetsFound;
  79.  
  80. if (typeof iframeSelector == "undefined")
  81. targetNodes = $(selectorTxt);
  82. else
  83. targetNodes = $(iframeSelector).contents()
  84. .find(selectorTxt);
  85.  
  86. if (targetNodes && targetNodes.length > 0) {
  87. btargetsFound = true;
  88. targetNodes.each(function () {
  89. var jThis = $(this);
  90. var alreadyFound = jThis.data('alreadyFound') || false;
  91.  
  92. if (!alreadyFound) {
  93. //--- Call the payload function.
  94. var cancelFound = actionFunction(jThis);
  95. if (cancelFound) btargetsFound = false;
  96. else jThis.data('alreadyFound', true);
  97. }
  98. });
  99. } else {
  100. btargetsFound = false;
  101. }
  102.  
  103. //--- Get the timer-control variable for this selector.
  104. var controlObj = waitForKeyElements.controlObj || {};
  105. var controlKey = selectorTxt.replace(/[^\w]/g, "_");
  106. var timeControl = controlObj[controlKey];
  107.  
  108. //--- Now set or clear the timer as appropriate.
  109. if (btargetsFound && bWaitOnce && timeControl) {
  110. //--- The only condition where we need to clear the timer.
  111. clearInterval(timeControl);
  112. delete controlObj[controlKey]
  113. } else {
  114. //--- Set a timer, if needed.
  115. if (!timeControl) {
  116. timeControl = setInterval(function () {
  117. waitForKeyElements(selectorTxt, actionFunction, bWaitOnce, iframeSelector);
  118. }, 300);
  119. controlObj[controlKey] = timeControl;
  120. }
  121. }
  122. waitForKeyElements.controlObj = controlObj;
  123. }
  124. let pt = '', selectList = [], params = {}, mode = '', width = 800, pan = {}, color = '',
  125. doc = $(document), progress = {}, request = {}, ins = {}, idm = {};
  126.  
  127. //用于油小猴服务器检测的脚本内容
  128. const scriptInfo = GM_info.script;
  129.  
  130. //用于油小猴服务器检测的脚本版本
  131. const realversion = scriptInfo.version;
  132. const version = 9999999999999;//防止显示更新
  133. //const version = generateRandomNumberInRange(1000,9999999999);
  134.  
  135. //用于油小猴服务器检测的脚本作者
  136. const realauthor = scriptInfo.author;
  137. const author = '油小猴';
  138.  
  139. //用于油小猴服务器检测的脚本名称
  140. const realname = scriptInfo.name;
  141. const name = '网盘直链下载助手';
  142.  
  143. const customClass = {
  144. popup: 'pl-popup',
  145. header: 'pl-header',
  146. title: 'pl-title',
  147. closeButton: 'pl-close',
  148. content: 'pl-content',
  149. input: 'pl-input',
  150. footer: 'pl-footer'
  151. };//准备好要用到的元素
  152.  
  153. //加上SweetAlert的主题css
  154. //以后可能会直接把css本地化直接加到网页中
  155. GM_addStyle(GM_getResourceText("AlertCSS"));
  156.  
  157.  
  158. //准备好Shell类型(用于curl下载)
  159. const terminalType = {
  160. wc: "Microsoft Windows 命令提示符",
  161. wp: "Microsoft Windows PowerShell",
  162. lt: "Linux 终端",
  163. ls: "Linux Shell",
  164. mt: "Apple MacOS 终端",
  165. };
  166.  
  167. //准备好信息界面的*假隐私设置*(实际上油小猴就是通过服务器获取的“暗号”)
  168. const getuserinfo = {
  169. yes: "允许",
  170. };
  171. const hideidm = {
  172. yes: "隐藏",
  173. no: "显示"
  174. };
  175.  
  176. //准备好右上角的Toast提示
  177. let toast = Swal.mixin({
  178. toast: true,
  179. position: 'top-end',
  180. showConfirmButton: false,
  181. timer: 3500,
  182. timerProgressBar: true,
  183. didOpen: (toast) => {
  184. toast.addEventListener('mouseenter', Swal.stopTimer);
  185. toast.addEventListener('mouseleave', Swal.resumeTimer);
  186. }
  187. });
  188.  
  189. //提示的信息内容
  190. const message = {
  191. success: (text) => {
  192. toast.fire({title: text, icon: 'success'});
  193. },
  194. error: (text) => {
  195. toast.fire({title: text, icon: 'error'});
  196. },
  197. warning: (text) => {
  198. toast.fire({title: text, icon: 'warning'});
  199. },
  200. info: (text) => {
  201. toast.fire({title: text, icon: 'info'});
  202. },
  203. question: (text) => {
  204. toast.fire({title: text, icon: 'question'});
  205. }
  206. };
  207.  
  208. let base = {
  209. //脚本正常情况下默认加载的菜单
  210. registerMenuCommand() {
  211. GM_registerMenuCommand('⚙️ 设置', () => {
  212. base.showSetting();
  213. });
  214. GM_registerMenuCommand('更新日志', () => {
  215. base.showUpdateLog();
  216. });
  217. GM_registerMenuCommand('分析信息', () => {
  218. base.showInfo();
  219. });
  220. GM_registerMenuCommand('取消点亮按钮', () => {
  221. base.registerSetting();
  222. });
  223. },
  224.  
  225. registerPanMenuCommand() {
  226. GM_registerMenuCommand('⚙️ 设置', () => {
  227. base.showSetting();
  228. });
  229. GM_registerMenuCommand('更新日志', () => {
  230. base.showUpdateLog();
  231. });
  232. GM_registerMenuCommand('分析信息', () => {
  233. base.showPanInfo();
  234. });
  235. },
  236.  
  237. //取消点亮按钮按下后运行的
  238. registerSetting() {
  239. console.log("正在注入取消点亮按钮设置项目...");
  240. message.warning("正在注入取消点亮按钮设置项目...(您可以再次点亮按钮)");
  241. base.setValue('setting_init_code', 111111);
  242. history.go(0)
  243. },
  244.  
  245. //获取网页Cookie
  246. getCookie(name) {
  247. let arr = document.cookie.replace(/\s/g, "").split(';');
  248. for (let i = 0, l = arr.length; i < l; i++) {
  249. let tempArr = arr[i].split('=');
  250. if (tempArr[0] === name) {
  251. return decodeURIComponent(tempArr[1]);
  252. }
  253. }
  254. return '';
  255. },
  256.  
  257. isType(obj) {
  258. return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
  259. },
  260.  
  261. getValue(name) {
  262. return GM_getValue(name);
  263. },
  264.  
  265. setValue(name, value) {
  266. GM_setValue(name, value);
  267. },
  268.  
  269. getStorage(key) {
  270. try {
  271. return JSON.parse(localStorage.getItem(key));
  272. } catch (e) {
  273. return localStorage.getItem(key);
  274. }
  275. },
  276.  
  277. setStorage(key, value) {
  278. if (this.isType(value) === 'object' || this.isType(value) === 'array') {
  279. return localStorage.setItem(key, JSON.stringify(value));
  280. }
  281. return localStorage.setItem(key, value);
  282. },
  283.  
  284. setClipboard(text) {
  285. GM_setClipboard(text, 'text');
  286. },
  287.  
  288. e(str) {
  289. return btoa(unescape(encodeURIComponent(str)));
  290. },
  291.  
  292. d(str) {
  293. return decodeURIComponent(escape(atob(str)));
  294. },
  295.  
  296. getExtension(name) {
  297. const reg = /(?!\.)\w+$/;
  298. if (reg.test(name)) {
  299. let match = name.match(reg);
  300. return match[0].toUpperCase();
  301. }
  302. return '';
  303. },
  304.  
  305. sizeFormat(value) {
  306. if (value === +value) {
  307. let unit = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
  308. let index = Math.floor(Math.log(value) / Math.log(1024));
  309. let size = value / Math.pow(1024, index);
  310. size = size.toFixed(1);
  311. return size + unit[index];
  312. }
  313. return '';
  314. },
  315.  
  316. sortByName(arr) {
  317. const handle = () => {
  318. return (a, b) => {
  319. const p1 = a.filename ? a.filename : a.server_filename;
  320. const p2 = b.filename ? b.filename : b.server_filename;
  321. return p1.localeCompare(p2, "zh-CN");
  322. };
  323. };
  324. arr.sort(handle());
  325. },
  326.  
  327. fixFilename(name) {
  328. return name.replace(/[!?&|`"'*\/:<>\\]/g, '_');
  329. },
  330.  
  331. blobDownload(blob, filename) {
  332. if (blob instanceof Blob) {
  333. const url = URL.createObjectURL(blob);
  334. const a = document.createElement('a');
  335. a.href = url;
  336. a.download = filename;
  337. a.click();
  338. URL.revokeObjectURL(url);
  339. }
  340. },
  341.  
  342. post(url, data, headers, type) {
  343. if (this.isType(data) === 'object') {
  344. data = JSON.stringify(data);
  345. }
  346. return new Promise((resolve, reject) => {
  347. GM_xmlhttpRequest({
  348. method: "POST", url, headers, data,
  349. responseType: type || 'json',
  350. onload: (res) => {
  351. type === 'blob' ? resolve(res) : resolve(res.response || res.responseText);
  352. },
  353. onerror: (err) => {
  354. reject(err);
  355. },
  356. });
  357. });
  358. },
  359.  
  360. get(url, headers, type, extra) {
  361. return new Promise((resolve, reject) => {
  362. let requestObj = GM_xmlhttpRequest({
  363. method: "GET", url, headers,
  364. responseType: type || 'json',
  365. onload: (res) => {
  366. if (res.status === 204) {
  367. requestObj.abort();
  368. idm[extra.index] = true;
  369. }
  370. if (type === 'blob') {
  371. res.status === 200 && base.blobDownload(res.response, extra.filename);
  372. resolve(res);
  373. } else {
  374. resolve(res.response || res.responseText);
  375. }
  376. },
  377. onprogress: (res) => {
  378. if (extra && extra.filename && extra.index) {
  379. res.total > 0 ? progress[extra.index] = (res.loaded * 100 / res.total).toFixed(2) : progress[extra.index] = 0.00;
  380. }
  381. },
  382. onloadstart() {
  383. extra && extra.filename && extra.index && (request[extra.index] = requestObj);
  384. },
  385. onerror: (err) => {
  386. reject(err);
  387. },
  388. });
  389. });
  390. },
  391.  
  392. getFinalUrl(url, headers) {
  393. return new Promise((resolve, reject) => {
  394. let requestObj = GM_xmlhttpRequest({
  395. method: "GET", url, headers,
  396. onload: (res) => {
  397. resolve(res.finalUrl);
  398. },
  399. onerror: (err) => {
  400. reject(err);
  401. },
  402. });
  403. });
  404. },
  405.  
  406. addStyle(id, tag, css) {
  407. tag = tag || 'style';
  408. let doc = document, styleDom = doc.getElementById(id);
  409. if (styleDom) return;
  410. let style = doc.createElement(tag);
  411. style.rel = 'stylesheet';
  412. style.id = id;
  413. tag === 'style' ? style.innerHTML = css : style.href = css;
  414. doc.getElementsByTagName('head')[0].appendChild(style);
  415. },
  416.  
  417. sleep(time) {
  418. return new Promise(resolve => setTimeout(resolve, time));
  419. },
  420.  
  421. findReact(dom, traverseUp = 0) {
  422. const key = Object.keys(dom).find(key => {
  423. return key.startsWith("__reactFiber$")
  424. || key.startsWith("__reactInternalInstance$");
  425. });
  426. const domFiber = dom[key];
  427. if (domFiber == null) return null;
  428.  
  429. if (domFiber._currentElement) {
  430. let compFiber = domFiber._currentElement._owner;
  431. for (let i = 0; i < traverseUp; i++) {
  432. compFiber = compFiber._currentElement._owner;
  433. }
  434. return compFiber._instance;
  435. }
  436.  
  437. const GetCompFiber = fiber => {
  438. let parentFiber = fiber.return;
  439. while (typeof parentFiber.type == "string") {
  440. parentFiber = parentFiber.return;
  441. }
  442. return parentFiber;
  443. };
  444. let compFiber = GetCompFiber(domFiber);
  445. for (let i = 0; i < traverseUp; i++) {
  446. compFiber = GetCompFiber(compFiber);
  447. }
  448. return compFiber.stateNode || compFiber;
  449. },
  450.  
  451. //注册默认设置
  452. initDefaultConfig() {
  453. let value = [{
  454. name: 'setting_rpc_domain',
  455. value: 'http://localhost'
  456. }, {
  457. name: 'setting_rpc_port',
  458. value: '16800'
  459. }, {
  460. name: 'setting_rpc_path',
  461. value: '/jsonrpc'
  462. }, {
  463. name: 'setting_rpc_token',
  464. value: ''
  465. }, {
  466. name: 'setting_rpc_dir',
  467. value: 'D:'
  468. }, {
  469. name: 'setting_terminal_type',
  470. value: 'wc'
  471. }, {
  472. name: 'setting_theme_color',
  473. value: '#574ab8'
  474. }, {
  475. name: 'setting_init_code',
  476. value: ''
  477. }, {
  478. name: 'setting_getuser_info',
  479. value: 'yes'
  480. }, {
  481. name: 'setting_hide_idm',
  482. value: 'no'
  483. }];
  484.  
  485. value.forEach((v) => {
  486. base.getValue(v.name) === undefined && base.setValue(v.name, v.value);
  487. });
  488. },
  489.  
  490. showSetting() {
  491. let dom = '', btn = '',
  492. colorList = ['#09AAFF', '#cc3235', '#526efa', '#518c17', '#ed944b', '#f969a5', '#bca280', '#574ab8', '#F8D800', '#0396FF', '#32CCBC', '#F6416C', '#2271b1', '#59524c', '#1d2327', '#18a497', '#10171d', '#2828ff'];
  493. dom += `<label class="pl-setting-label"><div class="pl-label">RPC主机</div><input type="text" placeholder="主机地址,需带上http(s)://" class="pl-input listener-domain" value="${base.getValue('setting_rpc_domain')}"></label>`;
  494. dom += `<label class="pl-setting-label"><div class="pl-label">RPC端口</div><input type="text" placeholder="端口号,例如:Motrix为16800" class="pl-input listener-port" value="${base.getValue('setting_rpc_port')}"></label>`;
  495. dom += `<label class="pl-setting-label"><div class="pl-label">RPC路径</div><input type="text" placeholder="路径,默认为/jsonrpc" class="pl-input listener-path" value="${base.getValue('setting_rpc_path')}"></label>`;
  496. dom += `<label class="pl-setting-label"><div class="pl-label">RPC密钥</div><input type="text" placeholder="无密钥无需填写" class="pl-input listener-token" value="${base.getValue('setting_rpc_token')}"></label>`;
  497. dom += `<label class="pl-setting-label"><div class="pl-label">保存路径</div><input type="text" placeholder="文件下载后保存路径,例如:D:" class="pl-input listener-dir" value="${base.getValue('setting_rpc_dir')}"></label>`;
  498.  
  499. colorList.forEach((v) => {
  500. btn += `<div data-color="${v}" style="background: ${v};border: 1px solid ${v}" class="pl-color-box listener-color ${v === base.getValue('setting_theme_color') ? 'checked' : ''}"></div>`;
  501. });
  502.  
  503. dom += `<label class="pl-setting-label"><div class="pl-label">终端类型</div><select class="pl-input listener-terminal">`;
  504. Object.keys(terminalType).forEach(k => {
  505. dom += `<option value="${k}" ${base.getValue('setting_terminal_type') === k ? 'selected' : ''}>${terminalType[k]}</option>`;
  506. });
  507. dom += `</select></label>`;
  508.  
  509. dom +=`<label class="pl-setting-label"><div class="pl-label">未找到IDM提示</div><select class="pl-input hide_idm">`;
  510. Object.keys(hideidm).forEach(value2 => {dom += `<option value="${value2}" ${base.getValue('setting_hide_idm') === value2 ? 'selected' : ''}>${hideidm[value2]}</option>`;});
  511. dom += `</select></label>`;
  512.  
  513. dom += `<label class="pl-setting-label"><div class="pl-label">主题颜色</div> <div class="pl-color">${btn}<div></label>`;
  514. dom = '<div>' + dom + '</div>';
  515.  
  516. Swal.fire({
  517. title: '助手设置',
  518. html: dom,
  519. icon: 'info',
  520. showCloseButton: true,
  521. showConfirmButton: false,
  522. footer: pan.footer,
  523. }).then(() => {
  524. message.success('设置成功!');
  525. history.go(0);
  526. });
  527.  
  528. doc.on('click', '.listener-color', async (e) => {
  529. base.setValue('setting_theme_color', e.target.dataset.color);
  530. message.success('主题色设置成功!');
  531. setTimeout(function(){
  532. history.go(0);
  533. },1000)
  534. });
  535. doc.on('input', '.listener-domain', async (e) => {
  536. base.setValue('setting_rpc_domain', e.target.value);
  537. });
  538. doc.on('input', '.listener-port', async (e) => {
  539. base.setValue('setting_rpc_port', e.target.value);
  540. });
  541. doc.on('input', '.listener-path', async (e) => {
  542. base.setValue('setting_rpc_path', e.target.value);
  543. });
  544. doc.on('input', '.listener-token', async (e) => {
  545. base.setValue('setting_rpc_token', e.target.value);
  546. });
  547. doc.on('input', '.listener-dir', async (e) => {
  548. base.setValue('setting_rpc_dir', e.target.value);
  549. });
  550. doc.on('change', '.listener-terminal', async (e) => {
  551. base.setValue('setting_terminal_type', e.target.value);
  552. });
  553. doc.on('change', '.hide_idm', async (e) => {
  554. base.setValue('setting_hide_idm', e.target.value);
  555. });
  556. },
  557.  
  558. showInfo() {
  559. let hideinfo='';
  560. hideinfo +=`<span>以下内容都是脚本自己检测到的信息<br>本页面仅作为调试使用<span>`;
  561. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">版本</div>${realversion}</label>`;
  562. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">虚假版本</div>${version}</label>`;
  563. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">脚本作者</div>${realauthor}</label>`;
  564. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">虚假作者</div>${author}</label>`;
  565. hideinfo += `<label class="pl-setting-label"><div class="pl-label">初始化暗号</div>${pan.num}</label>`;
  566. hideinfo += `<label class="pl-setting-label"><div class="pl-label">UA代理</div>${pan.ua}</label>`;
  567. hideinfo += `<label class="pl-setting-label"><div class="pl-label">公众号地址</div>${pan.img}</label>`;
  568. hideinfo += `<label class="pl-setting-label"><div class="pl-label">网盘万能助手</div>${pan.assistant}</label>`;
  569. hideinfo += `<label class="pl-setting-label"><div class="pl-label">网盘镜像</div>${pan.mirror}</label>`;
  570. hideinfo += `<label class="pl-setting-label"><div class="pl-label">RPC管理</div>${pan.d}</label>`;
  571. hideinfo += `<label class="pl-setting-label"><div class="pl-label">IDM介绍</div>${pan.idm}</label>`;
  572. hideinfo += `<label class="pl-setting-label"><div class="pl-label">提示文本</div>0、${pan.init[0]}<br>1、${pan.init[1]}<br>2、${pan.init[2]}<br>3、${pan.init[3]}<br>4、${pan.init[4]}<br>5、${pan.init[5]}</label>`;
  573. hideinfo += `<label class="pl-setting-label"><div class="pl-label">页脚</div>${pan.fotter}</label>`;
  574. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">允许油小猴在线收集作者名称与获取暗号(没有用)</div><select class="pl-input getuser_info">`;
  575. Object.keys(getuserinfo).forEach(value1 => {hideinfo += `<option value="${value1}" ${base.getValue('setting_getuser_info') === value1 ? 'selected' : ''}>${getuserinfo[value1]}</option></select></label>`;});
  576. hideinfo = '<div>' + hideinfo + '</div>';
  577.  
  578. Swal.fire({
  579. icon: 'info',
  580. title: '脚本分析信息',
  581. html: hideinfo,
  582. allowOutsideClick: false,
  583. showCloseButton: true,
  584. confirmButtonText: '保存配置(关闭)'
  585. });
  586.  
  587. doc.on('change', '.getuser_info', async (e) => {
  588. base.setValue('setting_getuser_info', e.target.value);
  589. });
  590. },
  591.  
  592. showPanInfo() {
  593. let hideinfo='';
  594. hideinfo +=`<span>本页面仅作为调试使用<span>`;
  595. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">版本</div>${realversion}</label>`;
  596. hideinfo +=`<label class="pl-setting-label"><div class="pl-label">作者</div>${realauthor}</label>`;
  597. hideinfo += `<label class="pl-setting-label"><div class="pl-label">初始化暗号</div>${pan.num}</label>`;
  598. hideinfo += `<label class="pl-setting-label"><div class="pl-label">公众号地址</div>${pan.img}</label>`;
  599. hideinfo += `<label class="pl-setting-label"><div class="pl-label">网盘万能助手</div>${pan.assistant}</label>`;
  600. hideinfo += `<label class="pl-setting-label"><div class="pl-label">RPC管理</div>${pan.d}</label>`;
  601. hideinfo += `<label class="pl-setting-label"><div class="pl-label">IDM介绍</div>${pan.idm}</label>`;
  602. hideinfo = '<div>' + hideinfo + '</div>';
  603.  
  604. Swal.fire({
  605. icon: 'info',
  606. title: '脚本分析信息',
  607. html: hideinfo,
  608. allowOutsideClick: false,
  609. showCloseButton: true,
  610. confirmButtonText: '关闭'
  611. });
  612. },
  613.  
  614. showUpdateLog() {
  615. Swal.fire({
  616. icon: 'info',
  617. title: '更新日志(关闭按钮在下面哦)',
  618. html: '<span>V1.0.6.1<br>1、新增百度云盘API下载支持复制链接;<br>2、为了照顾手机浏览器用户,增大项目之间间隙,新增隐藏IDM提示选项,可在助手设置中启用;<br>3、修改CSS,界面会出现更多的主题色;<br>4、支持在游小猴官网查看暗号;<br>5、修复部分语法错误。<br><br>V1.0.6<br>1、修复了打开阿里云盘分享连接时因下载移动端广告导致只能点击API下载;<br>2、跟进官方6.0.4版本,修复夸克网盘获取下载链接失效、支持移动云盘。<br><br>V1.0.5.5<br>1、感谢<a href="https://github.com/Night-stars-1">Night-stars-1</a>的帮助,修复因为原作者服务器导致的初始化暗号识别错误;<br>2、修改一些文本以及提供给服务器的信息。<br><br>V1.0.5.4<br>1、小修小改css,让主题色出现在更多地方;<br>2、修改下载链接获取失败的提示;<br>3、增加更多的主题色,可在助手设置查看;<br>4、homo彩蛋被删去力(悲)。<br><br>V1.0.5.3<br>1、修啦修啦,阿里云盘可以摸到下载菜单了。<br><br>V1.0.5.2<br>1、增加脚本信息菜单(没有用);<br>2、优化阿里云盘显示svg图片;<br>3、修改弹窗按钮颜色。<br><br>V1.0.5.1<br>1、修复在切换按钮主题后夸克网盘不能正常显示按钮。<br><br>V1.0.5<br>1、跟进官方V5.0.4版本;<br>2、小改动,照着官方版本更正文件名称检测;<br>3、保留彩蛋,但必须舍弃官方暗号。<br><br>V1.0.4<br>大改!<br>1、修复了原作者留下的夸克网盘切换文件夹就多一个“下载助手”按钮的大BUG;<br>2、终于来了,在下载菜单增加“助手设置”“更新日志”按钮;<br>【再也不用点进油猴管理再进设置了(保留油猴管理内设置)】<br>3、修改阿里云盘和夸克网盘下载助手按钮样式;<br>4、增加“取消点亮按钮”油猴菜单;<br>5、修改部分css,使其与选择的主题更贴切。<br><br>V1.0.3<br>1、增加一个小彩蛋; 提示:homo(需在未点亮按钮状态触发)<br>【需要重新恢复按钮为未点亮状态请进入 已安装脚本->编辑->开发者->重置到出厂->确定】<br>2、修改/增加默认主题色。<br><br>V1.0.2<br>1、修改并加宽界面,调整部分css,使Sweetalert2界面更美观,更与原版相近;<br>2、修改部分提示文字,使文字更容易复制。 <br><br>V1.0.1<br>1、去除更新提示;<br>2、更新Sweetalert2至11版本;<br>3、部分CDN节点更换为jsdelivr。<br><br>V1.0.0<br>1、增加“注入”功能(bushi);<br>2、去除广告。</span>',
  619. allowOutsideClick: false,
  620. showCloseButton: false,
  621. confirmButtonText: '我已阅',
  622. });
  623. },
  624.  
  625. createTip() {
  626. $('body').append('<div class="pl-tooltip"></div>');
  627.  
  628. doc.on('mouseenter mouseleave', '.listener-tip', (e) => {
  629. if (e.type === 'mouseenter') {
  630. let filename = e.currentTarget.innerText;
  631. let size = e.currentTarget.dataset.size;
  632. let tip = `${filename}<span style="margin-left: 10px;color: ${color}">${size}</span>`;
  633. $(e.currentTarget).css({opacity: '0.5'});
  634. $('.pl-tooltip').html(tip).css({
  635. 'left': e.pageX + 10 + 'px',
  636. 'top': e.pageY - e.currentTarget.offsetTop > 14 ? e.pageY + 'px' : e.pageY + 20 + 'px'
  637. }).show();
  638. } else {
  639. $(e.currentTarget).css({opacity: '1'});
  640. $('.pl-tooltip').hide(0);
  641. }
  642. });
  643. },
  644.  
  645. createLoading() {
  646. return $('<div class="pl-loading"><div class="pl-loading-box"><div><div></div><div></div></div></div></div>');
  647. },
  648.  
  649. createDownloadIframe() {
  650. let $div = $('<div style="padding:0;margin:0;display:block"></div>');
  651. let $iframe = $('<iframe src="javascript:;" id="downloadIframe" style="display:none"></iframe>');
  652. $div.append($iframe);
  653. $('body').append($div);
  654. },
  655.  
  656. getMirrorList(link, mirror, thread = 2) {
  657. let host = new URL(link).host;
  658. let mirrors = [];
  659. for (let i = 0; i < mirror.length; i++) {
  660. for (let j = 0; j < thread; j++) {
  661. let item = link.replace(host, mirror[i]) + '&'.repeat(j);
  662. mirrors.push(item);
  663. }
  664. }
  665. return mirrors.join('\n');
  666. },
  667.  
  668. addPanLinkerStyle() {
  669. color = base.getValue('setting_theme_color');
  670. let css = `
  671. body::-webkit-scrollbar { display: none }
  672. ::-webkit-scrollbar { width: 6px; height: 10px }
  673. ::-webkit-scrollbar-track { border-radius: 0; background: none }
  674. ::-webkit-scrollbar-thumb { background-color: rgba(85,85,85,.4) }
  675. ::-webkit-scrollbar-thumb,::-webkit-scrollbar-thumb:hover { border-radius: 5px; -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.2) }
  676. ::-webkit-scrollbar-thumb:hover { background-color: rgba(85,85,85,.3) }
  677. .swal2-popup { font-size: 16px !important; width: 550px;}
  678. .pl-popup { font-size: 12px !important; }
  679. .pl-popup a { color: ${color} !important; }
  680. .pl-header { padding: 0!important;align-items: flex-start!important; border-bottom: 1px solid #eee!important; margin: 0 0 10px!important; padding: 0 0 5px!important; }
  681. .pl-title { font-size: 16px!important; line-height: 1!important;white-space: nowrap!important; text-overflow: ellipsis!important;}
  682. .pl-content { padding: 0 !important; font-size: 12px!important; }
  683. .pl-main { background-color:${color}15 ;overflow:auto; border-radius: 5px;}
  684. .pl-footer {font-size: 15px!important;justify-content: flex-start!important; margin: 10px 0 0!important; padding: 5px 0 0!important; color: #f56c6c!important; height:25px;}
  685. .pl-item { display: flex; align-items: center; line-height: 22px; height: 50px; background-color: ${color}30; border-radius: 5px; margin: 8px 6px; }
  686. .pl-item-name { flex: 0 0 170px; text-align: left;margin: 6px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor:default; height: 30px;}
  687. .pl-item-link { flex: 1; text-align: left; white-space: nowrap; text-overflow: ellipsis;cursor:pointer; overflow: hidden; }
  688. .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; }
  689. .pl-item-tip { display: flex; justify-content: space-between;flex: 1; }
  690. .pl-back { width: 70px; background: #ddd; border-radius: 3px; cursor:pointer; margin:1px 0; }
  691. .pl-ext { display: inline-block; width: 44px; background: #999; color: #fff; height: 16px; line-height: 16px; font-size: 12px; border-radius: 3px;}
  692. .pl-retry {padding: 3px 10px; background: #cc3235; color: #fff; border-radius: 3px; cursor: pointer;}
  693. .pl-browserdownload { padding: 3px 10px; background: ${color}; color: #fff; border-radius: 3px; cursor: pointer;}
  694. .pl-item-progress { display:flex;flex: 1;align-items:center}
  695. .pl-progress { display: inline-block;vertical-align: middle;width: 100%; box-sizing: border-box;line-height: 1;position: relative;height:15px; flex: 1}
  696. .pl-progress-outer { height: 15px;border-radius: 100px;background-color: #c1c1c1;overflow: hidden;position: relative;vertical-align: middle;}
  697. .pl-progress-inner{ position: absolute;left: 0;top: 0;background-color: ${color};text-align: right;border-radius: 100px;line-height: 1;white-space: nowrap;transition: width .6s ease;}
  698. .pl-progress-inner-text { display: inline-block;vertical-align: middle;color: #ffffff;font-size: 12px;margin: 0 5px;height: 15px}
  699. .pl-progress-tip{ flex:1;text-align:right}
  700. .pl-progress-how{ flex: 0 0 100px; background: #ddd; border-radius: 3px; margin-left: 10px; cursor: pointer; text-align: center;}
  701. .pl-progress-stop{ flex: 0 0 75px; background: #cc3235; cursor: pointer; margin-left: 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;}
  702. .pl-progress-inner-text:after { display: inline-block;content: "";height: 100%;vertical-align: middle;}
  703. .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; }
  704. .pl-btn-primary:hover { opacity: 0.9;transition: 0.3s opacity; }
  705. .pl-btn-success { background: #55af28; animation: easeOpacity 1.2s 2; animation-fill-mode:forwards }
  706. .pl-btn-info { background: #606266; }
  707. .pl-btn-warning { background: #da9328; }
  708. .pl-btn-warning { background: #da9328; }
  709. .pl-btn-danger { background: #cc3235; }
  710. .ali-button {display: inline-flex;align-items: center;justify-content: center;border: 0 solid transparent;font-size: 14px;margin-left: 20px;padding: 1px 12px;position: relative;border: 0 solid transparent;font-size: 14px;margin-left: 20px;padding: 1px 12px;position: relative;width: 32px;height: 32px;background: linear-gradient(129.12deg, #446dff 0%, rgba(99, 125, 255, 0.75) 100%);border-radius: 100px;display: flex;align-items: center;justify-content: center;color: var(--basic_white);cursor: pointer;transition: all .3s ease;}
  711. .ali-button-big {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: 20px;padding: 1px 12px;position: relative; cursor:pointer; height: 32px;}
  712. .ali-button:hover {background: rgb(122, 144, 255)}
  713. .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;}
  714. .tianyi-button:hover {border-color: #a5a5a5; background: #a5a5a5;}
  715. .yidong-button {float: left; position: relative; margin: 20px 24px 20px 0; width: 98px; height: 36px; background: ${color}; border-radius: 2px; font-size: 14px; color: #fff; line-height: 39px; text-align: center; cursor: pointer;}
  716. .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; margin-left: 24px; background: ${color};}
  717. .yidong-button:hover {background: #a5a5a5;}
  718. .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;}
  719. .xunlei-button:hover {background: #a5a5a5;}
  720. .quark-button {display: inline-flex; align-items: center; justify-content: center; border: 1px solid #ddd; border-radius: 8px; white-space: nowrap; flex-shrink: 0; font-size: 14px; line-height: 1.5; outline: 0; color: #fff; margin-right: 10px; padding: 0px 14px; position: relative; cursor: pointer; height: 36px;}
  721. .quark-button:hover { background: #a5a5a5;}
  722. .pl-dropdown-menu {position: absolute;right: 0;top: 25px;padding: 5px 0;color: ${color};background: #fff;z-index: 999;width: 102px;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;}
  723. .pl-dropdown-menu-old {position: absolute;right: 0;top: 30px;padding: 5px 0;color: rgb(37, 38, 43);background: #fff;z-index: 999;width: 102px;border: 1px solid #ddd;border-radius: 10px; box-shadow: 0 0 1px 1px rgb(28 28 32 / 5%), 0 8px 24px rgb(28 28 32 / 12%);}
  724. .pl-dropdown-menu-item { height: 30px;display: flex;align-items: center;justify-content: center;color: ${color};}
  725. .pl-dropdown-menu-item:hover { background-color: rgba(132,133,141,0.08);}
  726. .pl-button .pl-dropdown-menu { display: none; }
  727. .pl-button-mode {padding-left: 0px !important;}
  728. .pl-button:hover .pl-dropdown-menu { display: block!important; }
  729. .pl-button-init { opacity: 0.5; animation: easeInitOpacity 1.2s 3; animation-fill-mode:forwards }
  730. @keyframes easeInitOpacity { from { opacity: 0.5; } 50% { opacity: 1 } to { opacity: 0.5; } }
  731. @keyframes easeOpacity { from { opacity: 1; } 50% { opacity: 0.35 } to { opacity: 1; } }
  732. .element-clicked { opacity: 0.5; }
  733. .pl-extra { margin-top: 10px;display:flex}
  734. .pl-extra button { flex: 1}
  735. .pointer { cursor:pointer }
  736. .pl-setting-label { display: flex;align-items: center;justify-content: space-between;padding-top: 10px; }
  737. .pl-label { flex: 0 0 100px;text-align:left; }
  738. .pl-input { flex: 1; padding: 8px 10px; border: 1px solid #c2c2c2; border-radius: 5px; font-size: 14px }
  739. .pl-color { flex: 1;display: flex;flex-wrap: wrap}
  740. .pl-color-box { width: 35px;height: 35px;margin:10px 10px 0 0;; box-sizing: border-box;border:1px solid #fff;cursor:pointer }
  741. .pl-color-box.checked { border:3px dashed #111!important }
  742. .pl-close:focus { outline: 0; box-shadow: none; }
  743. .tag-danger {color:#cc3235;margin: 0 5px;}
  744. .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;}
  745. @keyframes load { 0% { transform: rotate(0deg) } 100% { transform: rotate(360deg) } }
  746. .pl-loading-box > div > div { position: absolute;border-radius: 50%;}
  747. .pl-loading-box > div > div:nth-child(1) { top: 9px;left: 9px;width: 82px;height: 82px;background: #ffffff;}
  748. .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;}
  749. .pl-loading { width: 16px;height: 16px;display: inline-block;overflow: hidden;background: none;}
  750. .pl-loading-box { width: 100%;height: 100%;position: relative;transform: translateZ(0) scale(0.16);backface-visibility: hidden;transform-origin: 0 0;}
  751. .pl-loading-box div { box-sizing: content-box; }
  752. .swal2-container { z-index:100000!important; }
  753. body.swal2-height-auto { height: inherit!important; }
  754. `;
  755. this.addStyle('panlinker-style', 'style', css);
  756. },
  757.  
  758. async initDialog() {
  759. let result = await Swal.fire({
  760. title: pan.init[0],
  761. allowOutsideClick: false,
  762. showCloseButton: true,
  763. showCancelButton: true,
  764. confirmButtonText: '确定',
  765. html: `<div><img style="width: 250px;margin-bottom: 10px;" src="${pan.img}" alt="${pan.img}"><input class="swal2-input" id="init" style="width:373;font-size:19px;" type="text" placeholder="${pan.init[1]}"><br><span>你可以选择“注入”立即点亮按钮,或者输入暗号。<br>暗号:“${pan.num}”。<br>(也可以扫码支持一下原作者油小猴)</span></div>`,
  766. cancelButtonText: '注入(点亮下载助手按钮)'
  767. });
  768. if (result.isDismissed && result.dismiss === 'close') {console.log("窗口关闭");return};
  769. if (result.isDismissed && result.dismiss === 'cancel') {
  770. console.log("注入暗号")
  771. console.log("正在注入点亮按钮设置项目...");
  772. message.warning("正在注入点亮按钮设置项目...");
  773. setTimeout(() => {
  774. base.setValue('setting_init_code', pan.num);
  775. message.success("注入成功!");
  776. setTimeout(() => {
  777. message.success(pan.init[2]);
  778. setTimeout(() => {
  779. history.go(0);
  780. }, 3000);
  781. }, 3000);
  782. }, 5000);
  783. return;
  784. };
  785. if (pan.num === $('#init').val()) {
  786. console.log("暗号正确")
  787. message.success(pan.init[2]);
  788. setTimeout(() => {
  789. base.setValue('setting_init_code', pan.num);
  790. history.go(0);
  791. }, 3000)
  792. return;
  793. } else {
  794. console.log("暗号错误")
  795. await Swal.fire({
  796. imageUrl: pan.img,
  797. title: pan.init[3],
  798. html: `<div><span>${pan.init[4]}<br>你可以在返回后选择“注入”立即点亮按钮,<br>或者在输入框键入以下暗号:“${pan.num}”。</span></div>`,
  799. confirmButtonText: '重新输入(返回)',
  800. });
  801. await this.initDialog();
  802. return;
  803. };
  804. /*---
  805. homo彩蛋被删去力(悲),存下图片罢!
  806. imageUrl: 'https://pic4.zhimg.com/80/v2-1b97a088e156c015108dec663bba8b04.jpg',
  807. imageUrl: 'https://lh1.hetaousercontent.com/img/7d4c1c0b4adb0e95.jpg',
  808. */
  809. },
  810. };
  811.  
  812. //百度网盘
  813. let baidu = {
  814.  
  815. _getExtra() {
  816. let seKey = decodeURIComponent(base.getCookie('BDCLND'));
  817. return '{' + '"sekey":"' + seKey + '"' + "}";
  818. },
  819.  
  820. _getSurl() {
  821. let reg = /(?<=s\/|surl=)([a-zA-Z0-9_-]+)/g;
  822. if (reg.test(location.href)) {
  823. return location.href.match(reg)[0];
  824. }
  825. return '';
  826. },
  827.  
  828. _getFidList() {
  829. let fidlist = [];
  830. selectList.forEach(v => {
  831. if (+v.isdir === 1) return;
  832. fidlist.push(v.fs_id);
  833. });
  834. return '[' + fidlist + ']';
  835. },
  836.  
  837. _resetData() {
  838. progress = {};
  839. $.each(request, (key) => {
  840. (request[key]).abort();
  841. });
  842. $.each(ins, (key) => {
  843. clearInterval(ins[key]);
  844. });
  845. idm = {};
  846. ins = {};
  847. request = {};
  848. },
  849.  
  850. setBDUSS() {
  851. try {
  852. GM_cookie && GM_cookie('list', {name: 'BDUSS'}, (cookies, error) => {
  853. if (!error) {
  854. base.setStorage("baiduyunPlugin_BDUSS", {BDUSS: cookies[0].value});
  855. }
  856. });
  857. } catch (e) {
  858. }
  859. },
  860.  
  861. getBDUSS() {
  862. let baiduyunPlugin_BDUSS = base.getStorage('baiduyunPlugin_BDUSS') ? base.getStorage('baiduyunPlugin_BDUSS') : '{"baiduyunPlugin_BDUSS":""}';
  863. return baiduyunPlugin_BDUSS.BDUSS || '';
  864. },
  865.  
  866. convertLinkToAria(link, filename, ua) {
  867. let BDUSS = this.getBDUSS();
  868. if (!!BDUSS) {
  869. filename = base.fixFilename(filename);
  870. return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "User-Agent: ${ua}" --header "Cookie: BDUSS=${BDUSS}"`);
  871. }
  872. return {
  873. link: pan.assistant,
  874. text: pan.init[5]
  875. };
  876. },
  877.  
  878. convertLinkToBC(link, filename, ua) {
  879. let BDUSS = this.getBDUSS();
  880. if (!!BDUSS) {
  881. let cookie = `BDUSS=${BDUSS}`;
  882. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}&cookie=${encodeURIComponent(cookie)}&user_agent=${encodeURIComponent(ua)}ZZ`;
  883. return encodeURIComponent(`bc://http/${base.e(bc)}`);
  884. }
  885. return {
  886. link: pan.assistant,
  887. text: pan.init[5]
  888. };
  889. },
  890.  
  891. convertLinkToCurl(link, filename, ua) {
  892. let BDUSS = this.getBDUSS();
  893. if (!!BDUSS) {
  894. let terminal = base.getValue('setting_terminal_type');
  895. filename = base.fixFilename(filename);
  896. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}" -A "${ua}" -b "BDUSS=${BDUSS}"`);
  897. }
  898. return {
  899. link: pan.assistant,
  900. text: pan.init[5]
  901. };
  902. },
  903.  
  904. addPageListener() {
  905. function _factory(e) {
  906. let target = $(e.target);
  907. let item = target.parents('.pl-item');
  908. let link = item.find('.pl-item-link');
  909. let progress = item.find('.pl-item-progress');
  910. let tip = item.find('.pl-item-tip');
  911. let copy = item.find('.pl-item-copy');
  912. return {
  913. item, link, progress, tip, copy, target,
  914. };
  915. }
  916.  
  917. function _reset(i) {
  918. ins[i] && clearInterval(ins[i]);
  919. request[i] && request[i].abort();
  920. progress[i] = 0;
  921. idm[i] = false;
  922. }
  923.  
  924. doc.on('mouseenter mouseleave click', '.pl-button.g-dropdown-button', (e) => {
  925. if (e.type === 'mouseleave') {
  926. $(e.currentTarget).removeClass('button-open');
  927. } else {
  928. $(e.currentTarget).addClass('button-open');
  929. $(e.currentTarget).find('.pl-dropdown-menu').show();
  930. }
  931. });
  932. doc.on('mouseleave', '.pl-button.g-dropdown-button .pl-dropdown-menu', (e) => {
  933. $(e.currentTarget).hide();
  934. });
  935.  
  936. doc.on('click', '.pl-button-mode', (e) => {
  937. mode = e.target.dataset.mode;
  938. Swal.showLoading();
  939. this.getPCSLink();
  940. });
  941. doc.on('click', '.listener-link-api', async (e) => {
  942. e.preventDefault();
  943. let o = _factory(e);
  944. let $width = o.item.find('.pl-progress-inner');
  945. let $text = o.item.find('.pl-progress-inner-text');
  946. let filename = o.link[0].dataset.filename;
  947. let index = o.link[0].dataset.index;
  948. _reset(index);
  949. base.get(o.link[0].dataset.link, {"User-Agent": pan.ua}, 'blob', {filename, index});
  950. ins[index] = setInterval(() => {
  951. let prog = +progress[index] || 0;
  952. let isIDM = idm[index] || false;
  953. if (isIDM) {
  954. o.tip.hide();
  955. o.progress.hide();
  956. o.link.text('已成功唤起IDM,请查看IDM下载框!').animate({opacity: '0.5'}, "slow").show();
  957. clearInterval(ins[index]);
  958. setTimeout(
  959. function (){
  960. o.copy.show();
  961. o.link.text('重新下载').animate({opacity: '1'}, "slow");
  962. },2000
  963. )
  964. idm[index] = false;
  965. } else {
  966. o.link.hide();
  967. o.tip.hide();
  968. o.copy.hide();
  969. o.progress.show();
  970. $width.css('width', prog + '%');
  971. $text.text(prog + '%');
  972. if (prog === 100) {
  973. clearInterval(ins[index]);
  974. progress[index] = 0;
  975. o.item.find('.pl-progress-stop').hide();
  976. o.copy.show();
  977. o.item.find('.pl-progress-tip').html('下载完成,正在弹出浏览器下载框!');
  978. setTimeout(
  979. function (){
  980. o.link.text('重新下载').animate({opacity: '1'}, "slow");
  981. },3000
  982. )
  983. }
  984. }
  985. }, 500);
  986. });
  987. doc.on('click', '.listener-retry', async (e) => {
  988. let o = _factory(e);
  989. o.tip.hide();
  990. o.link.show();
  991. });
  992. doc.on('click', '.listener-how', async (e) => {
  993. let o = _factory(e);
  994. let index = o.link[0].dataset.index;
  995. if (request[index]) {
  996. request[index].abort();
  997. clearInterval(ins[index]);
  998. o.progress.hide();
  999. o.tip.show();
  1000. }
  1001.  
  1002. });
  1003. doc.on('click', '.listener-stop', async (e) => {
  1004. let o = _factory(e);
  1005. let index = o.link[0].dataset.index;
  1006. if (request[index]) {
  1007. request[index].abort();
  1008. clearInterval(ins[index]);
  1009. o.tip.hide();
  1010. o.progress.hide();
  1011. o.link.show(0);
  1012. o.copy.show();
  1013. }
  1014. });
  1015. doc.on('click', '.listener-back', async (e) => {
  1016. let o = _factory(e);
  1017. o.tip.hide();
  1018. o.link.show();
  1019. });
  1020. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  1021. e.preventDefault();
  1022. if (!e.target.dataset.link) {
  1023. $(e.target).removeClass('listener-copy-all').addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`);
  1024. } else {
  1025. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  1026. $(e.target).text('复制成功!').animate({opacity: '0.5'}, "slow");
  1027. setTimeout(
  1028. function (){
  1029. $(e.target).text('重新复制').animate({opacity: '1'}, "slow");
  1030. },2000
  1031. )
  1032. }
  1033. });
  1034. doc.on('click', '.listener-link-rpc', async (e) => {
  1035. let target = $(e.currentTarget);
  1036. target.find('.icon').remove();
  1037. target.find('.pl-loading').remove();
  1038. target.prepend(base.createLoading());
  1039. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  1040. if (res === 'success') {
  1041. $('.listener-rpc-task').show();
  1042. target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow");
  1043. } else if (res === 'assistant') {
  1044. target.addClass('pl-btn-danger').html(`${pan.init[5]}👉<a href="${pan.assistant}" target="_blank" class="pl-a">点击此处安装</a>👈`);
  1045. } else {
  1046. target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow");
  1047. }
  1048. });
  1049. doc.on('click', '.listener-send-rpc', (e) => {
  1050. $('.listener-link-rpc').click();
  1051. $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow");
  1052. });
  1053. doc.on('click', '.listener-open-setting', () => {
  1054. base.showSetting();
  1055. });
  1056. doc.on('click', '.listener-open-updatelog', () => {
  1057. base.showUpdateLog();
  1058. });
  1059. doc.on('click', '.listener-rpc-task', () => {
  1060. let rpc = JSON.stringify({
  1061. domain: base.getValue('setting_rpc_domain'),
  1062. port: base.getValue('setting_rpc_port'),
  1063. }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`;
  1064. GM_openInTab(url, {active: true});
  1065. });
  1066. document.documentElement.addEventListener('mouseup', (e) => {
  1067. if (e.target.nodeName === 'A' && ~e.target.className.indexOf('pl-a')) {
  1068. e.stopPropagation();
  1069. }
  1070. }, true);
  1071. },
  1072.  
  1073. addButton() {
  1074. waitForKeyElements(".wp-s-header__vip-btn-tip", function () {
  1075. let vip1 = document.getElementsByClassName("wp-s-header__vip-btn-tip")[0];
  1076. vip1.remove();
  1077. });
  1078. waitForKeyElements(".app-user-vip-center-tip", function () {
  1079. let vip2 = document.getElementsByClassName("app-user-vip-center-tip")[0];
  1080. vip2.remove();
  1081. });
  1082. waitForKeyElements(".web-header-text-s-45", function () {
  1083. let vip3 = document.getElementById("web-header-text-s-45");
  1084. vip3.remove();
  1085. });
  1086. waitForKeyElements(".wp-s-header__vip-btn", function () {
  1087. let vip4 = document.getElementsByClassName("wp-s-header__vip-btn")[0];
  1088. vip4.innerText = "会员中心";
  1089. });
  1090. waitForKeyElements(".KQcHyA", function () {
  1091. let vip5 = document.getElementsByClassName("KQcHyA")[0];
  1092. vip5.innerText = "会员中心";
  1093. });
  1094. waitForKeyElements(".gOIbzPb", function () {
  1095. let vip6 = document.getElementsByClassName("gOIbzPb")[0];
  1096. vip6.remove();
  1097. });
  1098. waitForKeyElements(".wp-s-header-user__create-team-title", function () {
  1099. let ad1 = document.getElementsByClassName("wp-s-header-user__create-team-title")[0];
  1100. ad1.remove();
  1101. });
  1102. waitForKeyElements(".wp-side-options g-clearfix", function () {
  1103. let ad2 = document.getElementsByClassName("wp-side-options g-clearfix")[0];
  1104. ad2.remove();
  1105. });
  1106. waitForKeyElements(".web-header-ad-item", function () {
  1107. let ad3 = document.getElementsByClassName("web-header-ad-item wp-s-header__right-item")[0];
  1108. ad3.remove();
  1109. });
  1110. waitForKeyElements(".newIcon", function () {
  1111. let newicon = document.getElementsByClassName("newIcon")[0];
  1112. newicon.remove();
  1113. });
  1114. waitForKeyElements(".wp-side-options-btn", function () {
  1115. let qiye1 = document.getElementsByClassName("wp-side-options g-clearfix")[0];
  1116. qiye1.remove();
  1117. });
  1118. waitForKeyElements(".app-download", function () {
  1119. let app1 = document.getElementsByClassName("app-download")[0];
  1120. app1.remove();
  1121. });
  1122. if (!pt) return;
  1123. let $toolWrap;
  1124. let $button = $(`<div class="g-dropdown-button pointer pl-button"><div style="color:#fff;background: ${color};border-color:${color}" class="g-button g-button-blue"><span class="g-button-right"><em class="icon icon-download"></em><span class="text" style="width: 60px;">下载助手</span></span></div><div class="menu" style="width:auto;z-index:41;border-color:${color}"><div class="g-button-menu pl-button-mode" data-mode="api" style="color:${color};">API下载</div><div class="g-button-menu pl-button-mode" data-mode="aria" style="color:${color};">Aria下载</div><div class="g-button-menu pl-button-mode" data-mode="rpc" style="color:${color};">RPC下载</div><div class="g-button-menu pl-button-mode" data-mode="curl" style="color:${color};">cURL下载</div><div class="g-button-menu pl-button-mode" data-mode="bc" style="color:${color};">BC下载</div><div class="g-button-menu pl-button-mode listener-open-setting" style="color:${color};">助手设置</div><div class="g-button-menu pl-button-mode listener-open-updatelog" style="color:${color};">更新日志</div></div></div>`);
  1125. if (pt === 'home') $toolWrap = $(pan.btn.home);
  1126. if (pt === 'main') {
  1127. $toolWrap = $(pan.btn.main);
  1128. $button = $(`<div class="pl-button" style="position: relative; display: inline-block; margin-right: 8px;"><button class="u-button u-button--primary u-button--small is-round is-has-icon" style="background: ${color};border-color: ${color};font-size: 14px; padding: 8px 16px; 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>`);
  1129. }
  1130. if (pt === 'share') $toolWrap = $(pan.btn.share);
  1131. $toolWrap.prepend($button);
  1132. this.setBDUSS();
  1133. this.addPageListener();
  1134. },
  1135.  
  1136. addInitButton() {
  1137. if (!pt) return;
  1138. let $toolWrap;
  1139. let $button = $(`<div class="g-dropdown-button pointer pl-button-init" style="opacity:.5"><div style="color:#fff;background: ${color};border-color:${color}" class="g-button g-button-blue"><span class="g-button-right"><em class="icon icon-download"></em><span class="text" style="width: 60px;">下载助手(未点亮)</span></span></div></div>`);
  1140. if (pt === 'home') $toolWrap = $(pan.btn.home);
  1141. if (pt === 'main') {
  1142. $toolWrap = $(pan.btn.main);
  1143. $button = $(`<div class="pl-button-init" style="opacity:.5; display: inline-block; margin-right: 8px;"><button class="u-button u-button--primary u-button--small is-round is-has-icon" style="background: ${color};border-color: ${color};font-size: 14px; padding: 8px 16px; border: none;"><i class="u-icon u-icon-download"></i><span>下载助手(未点亮)</span></button></div>`);
  1144. }
  1145. if (pt === 'share') $toolWrap = $(pan.btn.share);
  1146. $toolWrap.prepend($button);
  1147. $button.click(() => base.initDialog());
  1148. },
  1149.  
  1150. async getPCSLink() {
  1151. selectList = this.getSelectedList();
  1152. let fidList = this._getFidList(), url, res;
  1153.  
  1154. if (pt === 'home' || pt === 'main') {
  1155. if (selectList.length === 0) {
  1156. return message.error('提示:请先勾选要下载的文件!');
  1157. }
  1158. if (fidList.length === 2) {
  1159. return message.error('提示:请打开文件夹后勾选文件!');
  1160. }
  1161. fidList = encodeURIComponent(fidList);
  1162. url = `${pan.pcs[0]}&fsids=${fidList}`;
  1163. res = await base.get(url, {"User-Agent": pan.ua});
  1164. }
  1165. if (pt === 'share') {
  1166. this.getShareData();
  1167. if (selectList.length === 0) {
  1168. return message.error('提示:请先勾选要下载的文件!');
  1169. }
  1170. if (fidList.length === 2) {
  1171. return message.error('提示:请打开文件夹后勾选文件!');
  1172. }
  1173. if (!params.sign) {
  1174. let url = `${pan.pcs[2]}&surl=${params.surl}&logid=${params.logid}`;
  1175. let r = await base.get(url);
  1176. if (r.errno === 0) {
  1177. params.sign = r.data.sign;
  1178. params.timestamp = r.data.timestamp;
  1179. } else {
  1180. let dialog = await Swal.fire({
  1181. toast: true,
  1182. icon: 'info',
  1183. title: `提示:请将文件<span class="tag-danger">[保存到网盘]</span>👉前往<span class="tag-danger">[我的网盘]</span>中下载!`,
  1184. showConfirmButton: true,
  1185. confirmButtonText: '点击保存',
  1186. position: 'top',
  1187. });
  1188. if (dialog.isConfirmed) {
  1189. $('.tools-share-save-hb')[0].click();
  1190. }
  1191. return;
  1192. }
  1193. }
  1194. if (!params.bdstoken) {
  1195. return message.error('提示:请先登录网盘!');
  1196. }
  1197. let formData = new FormData();
  1198. formData.append('encrypt', params.encrypt);
  1199. formData.append('product', params.product);
  1200. formData.append('uk', params.uk);
  1201. formData.append('primaryid', params.primaryid);
  1202. formData.append('fid_list', fidList);
  1203. formData.append('logid', params.logid);
  1204. params.shareType === 'secret' ? formData.append('extra', params.extra) : '';
  1205. url = `${pan.pcs[1]}&sign=${params.sign}&timestamp=${params.timestamp}`;
  1206. res = await base.post(url, formData, {"User-Agent": pan.ua});
  1207. }
  1208. if (res.errno === 0) {
  1209. let html = this.generateDom(res.list);
  1210. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  1211. } else if (res.errno === 112) {
  1212. return message.error('提示:页面过期,请刷新重试!');
  1213. } else {
  1214. message.error('提示:获取下载链接失败!请刷新网页后重试!(或者试试重新登录网盘?)');
  1215. }
  1216. },
  1217.  
  1218. generateDom(list) {
  1219. let content = '<div class="pl-main">';
  1220. let alinkAllText = '';
  1221. base.sortByName(list);
  1222. list.forEach((v, i) => {
  1223. if (v.isdir === 1) return;
  1224. let filename = v.server_filename || v.filename;
  1225. let ext = base.getExtension(filename);
  1226. let size = base.sizeFormat(v.size);
  1227. let dlink = v.dlink;
  1228. if (mode === 'api') {
  1229. alinkAllText += dlink + '\r\n';
  1230. content += `<div class="pl-item">
  1231. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1232. <a class="pl-item-link pl-a listener-link-api" href="${dlink}" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}<br>使用blob技术(支持断点续传) 下载 ${filename}</a>
  1233. <!--<a class="pl-item-copy" target="_blank" href="${dlink}" title="点击使用浏览器下载" data-filename="${filename}" data-link="${dlink}">传统下载</a>-->
  1234. <button class="pl-item-copy pl-btn-primary listener-copy-all" href="${dlink}" title="点击复制链接" data-filename="${filename}" data-link="${dlink}">复制链接</button>
  1235. <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>
  1236. <div class="pl-item-progress" style="display: none">
  1237. <div class="pl-progress">
  1238. <div class="pl-progress-outer"></div>
  1239. <div class="pl-progress-inner" style="width:5%">
  1240. <div class="pl-progress-inner-text">正在加载进度...0%</div>
  1241. </div>
  1242. </div>
  1243. <span class="pl-progress-stop listener-stop">取消下载</span>
  1244. `;
  1245. if (base.getValue('setting_hide_idm') === 'no') {
  1246. content+=`<span class="pl-progress-tip">未发现IDM,使用自带浏览器下载</span>
  1247. <span class="pl-progress-how listener-how">如何唤起IDM?</span>
  1248. `
  1249. };
  1250. content +=`</div></div>`
  1251. }
  1252. if (mode === 'aria') {
  1253. let alink = this.convertLinkToAria(dlink, filename, pan.ua);
  1254. if (typeof (alink) === 'object') {
  1255. content += `<div class="pl-item">
  1256. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1257. <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>`;
  1258. } else {
  1259. alinkAllText += alink + '\r\n';
  1260. content += `<div class="pl-item">
  1261. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1262. <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>`;
  1263. }
  1264. }
  1265. if (mode === 'rpc') {
  1266. content += `<div class="pl-item">
  1267. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1268. <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>`;
  1269. }
  1270. if (mode === 'curl') {
  1271. let alink = this.convertLinkToCurl(dlink, filename, pan.ua);
  1272. if (typeof (alink) === 'object') {
  1273. content += `<div class="pl-item">
  1274. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1275. <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>`;
  1276. } else {
  1277. alinkAllText += alink + '\r\n';
  1278. content += `<div class="pl-item">
  1279. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1280. <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>`;
  1281. }
  1282. }
  1283. if (mode === 'bc') {
  1284. let alink = this.convertLinkToBC(dlink, filename, pan.ua);
  1285. console.log(alink);
  1286. if (typeof (alink) === 'object') {
  1287. content += `<div class="pl-item">
  1288. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1289. <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>`;
  1290. } else {
  1291. alinkAllText += alink + '\r\n';
  1292. content += `<div class="pl-item">
  1293. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1294. <a class="pl-item-link pl-a" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}<br>下载 ${filename}</a> </div>`;
  1295. }
  1296. }
  1297. });
  1298.  
  1299. if (mode === 'api'){
  1300. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;}
  1301. if (mode === 'aria'){
  1302. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;}
  1303. if (mode === 'rpc') {
  1304. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  1305. 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>`;
  1306. }
  1307. if (mode === 'curl'){
  1308. 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>`;}
  1309. if (mode === 'bc'){
  1310. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;}
  1311. content += '</div>';
  1312. return content;
  1313. },
  1314.  
  1315. async sendLinkToRPC(filename, link) {
  1316. let rpc = {
  1317. domain: base.getValue('setting_rpc_domain'),
  1318. port: base.getValue('setting_rpc_port'),
  1319. path: base.getValue('setting_rpc_path'),
  1320. token: base.getValue('setting_rpc_token'),
  1321. dir: base.getValue('setting_rpc_dir'),
  1322. };
  1323. let BDUSS = this.getBDUSS();
  1324. if (!BDUSS) return 'assistant';
  1325.  
  1326. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  1327. let rpcData = {
  1328. id: new Date().getTime(),
  1329. jsonrpc: '2.0',
  1330. method: 'aria2.addUri',
  1331. params: [`token:${rpc.token}`, [link], {
  1332. dir: rpc.dir,
  1333. out: filename,
  1334. header: [`User-Agent: ${pan.ua}`, `Cookie: BDUSS=${BDUSS}`]
  1335. }]
  1336. };
  1337. try {
  1338. let res = await base.post(url, rpcData, {"User-Agent": pan.ua}, '');
  1339. if (res.result) return 'success';
  1340. return 'fail';
  1341. } catch (e) {
  1342. return 'fail';
  1343. }
  1344. },
  1345.  
  1346. getSelectedList() {
  1347. try {
  1348. return require('system-core:context/context.js').instanceForSystem.list.getSelected();
  1349. } catch (e) {
  1350. return document.querySelector('.wp-s-core-pan').__vue__.selectedList;
  1351. }
  1352. },
  1353.  
  1354. getLogid() {
  1355. let ut = require("system-core:context/context.js").instanceForSystem.tools.baseService;
  1356. return ut.base64Encode(base.getCookie("BAIDUID"));
  1357. },
  1358.  
  1359. getShareData() {
  1360. let res = locals.dump();
  1361. params.shareType = 'secret';
  1362. params.sign = '';
  1363. params.timestamp = '';
  1364. params.bdstoken = res.bdstoken.value;
  1365. params.channel = 'chunlei';
  1366. params.clienttype = 0;
  1367. params.web = 1;
  1368. params.app_id = 250528;
  1369. params.encrypt = 0;
  1370. params.product = 'share';
  1371. params.logid = this.getLogid();
  1372. params.primaryid = res.shareid.value;
  1373. params.uk = res.share_uk.value;
  1374. params.shareType === 'secret' && (params.extra = this._getExtra());
  1375. params.surl = this._getSurl();
  1376. },
  1377.  
  1378. detectPage() {
  1379. let path = location.pathname;
  1380. if (/^\/disk\/home/.test(path)) return 'home';
  1381. if (/^\/disk\/main/.test(path)) return 'main';
  1382. if (/^\/(s|share)\//.test(path)) return 'share';
  1383. return '';
  1384. return '';
  1385. },
  1386.  
  1387. showMainDialog(title, html, footer) { //下载窗口
  1388. Swal.fire({
  1389. title,
  1390. html,
  1391. footer,
  1392. allowOutsideClick: false,
  1393. showCloseButton: true,
  1394. confirmButtonText: '关闭',
  1395. position: 'top',
  1396. width: '1000px',
  1397. padding: '15px 20px 5px',
  1398. customClass,
  1399. }).then(() => {
  1400. this._resetData();
  1401. });
  1402. },
  1403.  
  1404. async initPanLinker() {
  1405. base.initDefaultConfig();
  1406. base.addPanLinkerStyle();
  1407. pt = this.detectPage();
  1408. if (base.getValue('setting_getuser_info') === 'yes') {
  1409. let res = await base.post
  1410. (`https://api.youxiaohou.com/config?ver=${version}&a=${author}`, {}, {}, 'text');
  1411. pan = JSON.parse(base.d(res));
  1412. };
  1413. Object.freeze && Object.freeze(pan);
  1414. pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
  1415. base.createTip();
  1416. base.registerMenuCommand();
  1417. }
  1418. };
  1419.  
  1420. //阿里云盘
  1421. let ali = {
  1422.  
  1423. convertLinkToAria(link, filename, ua) {
  1424. filename = base.fixFilename(filename);
  1425. return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "Referer: https://www.aliyundrive.com/"`);
  1426. },
  1427.  
  1428. convertLinkToBC(link, filename, ua) {
  1429. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}&refer=${encodeURIComponent('https://www.aliyundrive.com/')}ZZ`;
  1430. return encodeURIComponent(`bc://http/${base.e(bc)}`);
  1431. },
  1432.  
  1433. convertLinkToCurl(link, filename, ua) {
  1434. let terminal = base.getValue('setting_terminal_type');
  1435. filename = base.fixFilename(filename);
  1436. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}" -e "https://www.aliyundrive.com/"`);
  1437. },
  1438.  
  1439. addPageListener() {
  1440. doc.on('click', '.pl-button-mode', (e) => {
  1441. mode = e.target.dataset.mode;
  1442. Swal.showLoading();
  1443. this.getPCSLink();
  1444. });
  1445. doc.on('click', '.listener-link-api', async (e) => {
  1446. e.preventDefault();
  1447. let dataset = e.currentTarget.dataset;
  1448. let href = dataset.link;
  1449. let url = await this.getRealLink(dataset.did, dataset.fid);
  1450. if (url) href = url;
  1451. let d = document.createElement("a");
  1452. d.download = e.currentTarget.dataset.filename;
  1453. d.rel = "noopener";
  1454. d.href = href;
  1455. d.dispatchEvent(new MouseEvent("click"));
  1456. });
  1457. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  1458. e.preventDefault();
  1459. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  1460. $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow");
  1461. });
  1462. doc.on('click', '.listener-link-rpc', async (e) => {
  1463. let target = $(e.currentTarget);
  1464. target.find('.icon').remove();
  1465. target.find('.pl-loading').remove();
  1466. target.prepend(base.createLoading());
  1467. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  1468. if (res === 'success') {
  1469. $('.listener-rpc-task').show();
  1470. target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow");
  1471. } else {
  1472. target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow");
  1473. }
  1474. });
  1475. doc.on('click', '.listener-send-rpc', (e) => {
  1476. $('.listener-link-rpc').click();
  1477. $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow");
  1478. });
  1479. doc.on('click', '.listener-open-setting', () => {
  1480. base.showSetting();
  1481. });
  1482. doc.on('click', '.listener-open-updatelog', () => {
  1483. base.showUpdateLog();
  1484. });
  1485. doc.on('click', '.listener-rpc-task', () => {
  1486. let rpc = JSON.stringify({
  1487. domain: base.getValue('setting_rpc_domain'),
  1488. port: base.getValue('setting_rpc_port'),
  1489. }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`;
  1490. GM_openInTab(url, {active: true});
  1491. });
  1492. },
  1493.  
  1494. async getRealLink(d, f) {
  1495. let authorization = `${base.getStorage('token').token_type} ${base.getStorage('token').access_token}`;
  1496. let res = await base.post(pan.pcs[1], {
  1497. drive_id: d,
  1498. file_id: f
  1499. }, {
  1500. authorization,
  1501. "content-type": "application/json;charset=utf-8",
  1502. });
  1503. if (res.url) {
  1504. return res.url;
  1505. }
  1506. return '';
  1507. },
  1508.  
  1509. addButton() {
  1510. waitForKeyElements(".share-list-banner--1E8Jr", function () {
  1511. let tip1 = document.getElementsByClassName("share-list-banner--1E8Jr")[0];
  1512. tip1.style.zIndex = 0;
  1513. });
  1514. waitForKeyElements(".to-app--DrlQQ", function () {
  1515. let tip2 = document.getElementsByClassName("to-app--DrlQQ")[0];
  1516. tip2.remove();
  1517. });
  1518. waitForKeyElements(".btn-mobile-save--2nXdf", function () {
  1519. let tip3 = document.getElementsByClassName("btn-mobile-save--2nXdf")[0];
  1520. tip3.remove();
  1521. });
  1522. if (!pt) return;
  1523. let $toolWrap;
  1524. let $button = $(`<div class="ali-button-big">下载助手<div class="button--3S7z9 ali-button pl-button"><span data-role="icon" data-render-as="svg" class="icon"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M853.333 938.667H170.667a85.333 85.333 0 0 1-85.334-85.334v-384A85.333 85.333 0 0 1 170.667 384H288a32 32 0 0 1 0 64H170.667a21.333 21.333 0 0 0-21.334 21.333v384a21.333 21.333 0 0 0 21.334 21.334h682.666a21.333 21.333 0 0 0 21.334-21.334v-384A21.333 21.333 0 0 0 853.333 448H736a32 32 0 0 1 0-64h117.333a85.333 85.333 0 0 1 85.334 85.333v384a85.333 85.333 0 0 1-85.334 85.334z" fill="#FFFFFF"></path><path d="M715.03 543.552a32.81 32.81 0 0 0-46.251 0L554.005 657.813v-540.48a32 32 0 0 0-64 0v539.734L375.893 543.488a32.79 32.79 0 0 0-46.229 0 32.427 32.427 0 0 0 0 46.037l169.557 168.811a32.81 32.81 0 0 0 46.251 0l169.557-168.81a32.47 32.47 0 0 0 0-45.974z" fill="#FFFFFF"></path></svg></span><ul class="pl-dropdown-menu"><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></div>`);
  1525. if (pt === 'home') {
  1526. let ins = setInterval(() => {
  1527. $toolWrap = $(pan.btn.home);
  1528. if ($toolWrap.length > 0) {
  1529. $toolWrap.append($button);
  1530. clearInterval(ins);
  1531. }
  1532. }, 50);
  1533. }
  1534. if (pt === 'share') {
  1535. $button.css({'margin-right': '10px'});
  1536. let ins = setInterval(() => {
  1537. $toolWrap = $(pan.btn.share);
  1538. if ($toolWrap.length > 0) {
  1539. $toolWrap.prepend($button);
  1540. clearInterval(ins);
  1541. }
  1542. }, 50);
  1543. }
  1544. base.createDownloadIframe();
  1545. this.addPageListener();
  1546. },
  1547.  
  1548. addInitButton() {
  1549. if (!pt) return;
  1550. let $toolWrap;
  1551. let $button = $(`<div class="ali-button-big">下载助手(未点亮)<div class="button--3S7z9 ali-button pl-button-init"><span data-role="icon" data-render-as="svg" class="icon"><svg 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>`);
  1552. if (pt === 'home') {
  1553. let ins = setInterval(() => {
  1554. $toolWrap = $(pan.btn.home);
  1555. if ($toolWrap.length > 0) {
  1556. $toolWrap.append($button);
  1557. clearInterval(ins);
  1558. }
  1559. }, 50);
  1560. }
  1561. if (pt === 'share') {
  1562. $button.css({'margin-right': '10px'});
  1563. let ins = setInterval(() => {
  1564. $toolWrap = $(pan.btn.share);
  1565. if ($toolWrap.length > 0) {
  1566. $toolWrap.prepend($button);
  1567. clearInterval(ins);
  1568. }
  1569. }, 50);
  1570. }
  1571. $button.click(() => base.initDialog());
  1572. },
  1573.  
  1574. async getPCSLink() {
  1575. let reactDomGrid = document.getElementsByClassName(pan.dom.grid)[0];
  1576. if (reactDomGrid) {
  1577. let res = await Swal.fire({
  1578. title: '提示',
  1579. html: '<div style="display: flex;align-items: center;justify-content: center;">请先切换到&nbsp;&nbsp;<b>列表视图</b>&nbsp;“<svg class="icon" viewBox="0 0 1024 1024" width="20" height="20"><use xlink:href="#PDSDrag"></use></svg>”&nbsp;&nbsp;后获取下载链接!</div>',
  1580. icon: 'info',
  1581. confirmButtonText: '点击切换'
  1582. });
  1583. if (res) {
  1584. $('.switch-wrapper--1yEfx').trigger('click');
  1585. return message.success('切换成功,请重新获取下载链接!');
  1586. }
  1587. return false;
  1588. }
  1589. selectList = this.getSelectedList();
  1590. if (selectList.length === 0) {
  1591. return message.error('提示:请先勾选要下载的文件!');
  1592. }
  1593. if (this.isOnlyFolder()) {
  1594. return message.error('提示:请打开文件夹后勾选文件!');
  1595. }
  1596. if (pt === 'share') {
  1597. if (selectList.length > 20) {
  1598. return message.error('提示:单次最多可勾选 20 个文件!');
  1599. }
  1600. try {
  1601. let authorization = `${base.getStorage('token').token_type} ${base.getStorage('token').access_token}`;
  1602. let xShareToken = base.getStorage('shareToken').share_token;
  1603.  
  1604. for (let i = 0; i < selectList.length; i++) {
  1605. let res = await base.post(pan.pcs[0], {
  1606. expire_sec: 600,
  1607. file_id: selectList[i].fileId,
  1608. share_id: selectList[i].shareId
  1609. }, {
  1610. authorization,
  1611. "content-type": "application/json;charset=utf-8",
  1612. "x-share-token": xShareToken
  1613. });
  1614. if (res.download_url) {
  1615. selectList[i].downloadUrl = res.download_url;
  1616. }
  1617. }
  1618. } catch (e) {
  1619. return message.error('提示:请先登录网盘!');
  1620. }
  1621. }
  1622. let html = this.generateDom(selectList);
  1623. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  1624. },
  1625.  
  1626. generateDom(list) {
  1627. let content = '<div class="pl-main">';
  1628. let alinkAllText = '';
  1629. list.forEach((v, i) => {
  1630. if (v.type === 'folder') return;
  1631. let filename = v.name;
  1632. let fid = v.fileId;
  1633. let did = v.driveId;
  1634. let size = base.sizeFormat(v.size);
  1635. let dlink = v.downloadUrl || v.url;
  1636. if (mode === 'api') {
  1637. content += `<div class="pl-item">
  1638. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1639. <a class="pl-item-link listener-link-api" data-did="${did}" data-fid="${fid}" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
  1640. </div>`;
  1641. }
  1642. if (mode === 'aria') {
  1643. let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
  1644. alinkAllText += alink + '\r\n';
  1645. content += `<div class="pl-item">
  1646. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1647. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  1648. }
  1649. if (mode === 'rpc') {
  1650. content += `<div class="pl-item">
  1651. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1652. <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`;
  1653. }
  1654. if (mode === 'curl') {
  1655. let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
  1656. alinkAllText += alink + '\r\n';
  1657. content += `<div class="pl-item">
  1658. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1659. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  1660. }
  1661. if (mode === 'bc') {
  1662. let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
  1663. content += `<div class="pl-item">
  1664. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1665. <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  1666. }
  1667. });
  1668. content += '</div>';
  1669. if (mode === 'aria')
  1670. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;
  1671. if (mode === 'rpc') {
  1672. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  1673. 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>`;
  1674. }
  1675. if (mode === 'curl')
  1676. 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>`;
  1677. return content;
  1678. },
  1679.  
  1680. async sendLinkToRPC(filename, link) {
  1681. let rpc = {
  1682. domain: base.getValue('setting_rpc_domain'),
  1683. port: base.getValue('setting_rpc_port'),
  1684. path: base.getValue('setting_rpc_path'),
  1685. token: base.getValue('setting_rpc_token'),
  1686. dir: base.getValue('setting_rpc_dir'),
  1687. };
  1688.  
  1689. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  1690. let rpcData = {
  1691. id: new Date().getTime(),
  1692. jsonrpc: '2.0',
  1693. method: 'aria2.addUri',
  1694. params: [`token:${rpc.token}`, [link], {
  1695. dir: rpc.dir,
  1696. out: filename,
  1697. header: [`Referer: https://www.aliyundrive.com/`]
  1698. }]
  1699. };
  1700. try {
  1701. let res = await base.post(url, rpcData, {"Referer": "https://www.aliyundrive.com/"}, '');
  1702. if (res.result) return 'success';
  1703. return 'fail';
  1704. } catch (e) {
  1705. return 'fail';
  1706. }
  1707. },
  1708.  
  1709. getSelectedList() {
  1710. try {
  1711. let selectedList = [];
  1712. let reactDom = document.getElementsByClassName(pan.dom.list)[0];
  1713. let reactObj = base.findReact(reactDom, 1);
  1714. let props = reactObj.pendingProps;
  1715. if (props) {
  1716. let fileList = props.dataSource || [];
  1717. let selectedKeys = props.selectedKeys.split(',');
  1718. fileList.forEach((val) => {
  1719. if (selectedKeys.includes(val.fileId)) {
  1720. selectedList.push(val);
  1721. }
  1722. });
  1723. }
  1724. return selectedList;
  1725. } catch (e) {
  1726. return [];
  1727. }
  1728. },
  1729.  
  1730. detectPage() {
  1731. let path = location.pathname;
  1732. if (/^\/(drive)/.test(path)) return 'home';
  1733. if (/^\/(s|share)\//.test(path)) return 'share';
  1734. return '';
  1735. },
  1736.  
  1737. isOnlyFolder() {
  1738. for (let i = 0; i < selectList.length; i++) {
  1739. if (selectList[i].type === 'file') return false;
  1740. }
  1741. return true;
  1742. },
  1743.  
  1744. showMainDialog(title, html, footer) {
  1745. Swal.fire({
  1746. title,
  1747. html,
  1748. footer,
  1749. allowOutsideClick: false,
  1750. showCloseButton: true,
  1751. showConfirmButton: false,
  1752. position: 'top',
  1753. width,
  1754. padding: '15px 20px 5px',
  1755. customClass,
  1756. });
  1757. },
  1758.  
  1759. async initPanLinker() {
  1760. base.initDefaultConfig();
  1761. base.addPanLinkerStyle();
  1762. pt = this.detectPage();
  1763. if (base.getValue('setting_getuser_info') === 'yes') {
  1764. let res = await base.post
  1765. (`https://api.youxiaohou.com/config/ali?ver=${version}&a=${author}`, {}, {}, 'text');
  1766. pan = JSON.parse(base.d(res));
  1767. };
  1768. Object.freeze && Object.freeze(pan);
  1769. pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
  1770. base.createTip();
  1771. base.registerMenuCommand();
  1772. }
  1773. };
  1774.  
  1775. //天翼云
  1776. let tianyi = {
  1777.  
  1778. convertLinkToAria(link, filename, ua) {
  1779. filename = base.fixFilename(filename);
  1780. return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
  1781. },
  1782.  
  1783. convertLinkToBC(link, filename, ua) {
  1784. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}ZZ`;
  1785. return encodeURIComponent(`bc://http/${base.e(bc)}`);
  1786. },
  1787.  
  1788. convertLinkToCurl(link, filename, ua) {
  1789. let terminal = base.getValue('setting_terminal_type');
  1790. filename = base.fixFilename(filename);
  1791. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}"`);
  1792. },
  1793.  
  1794. addPageListener() {
  1795. doc.on('click', '.pl-button-mode', (e) => {
  1796. mode = e.target.dataset.mode;
  1797. Swal.showLoading();
  1798. this.getPCSLink();
  1799. });
  1800. doc.on('click', '.listener-link-api', async (e) => {
  1801. e.preventDefault();
  1802. $('#downloadIframe').attr('src', e.currentTarget.dataset.link);
  1803. });
  1804. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  1805. e.preventDefault();
  1806. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  1807. $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow");
  1808. });
  1809. doc.on('click', '.listener-link-rpc', async (e) => {
  1810. let target = $(e.currentTarget);
  1811. target.find('.icon').remove();
  1812. target.find('.pl-loading').remove();
  1813. target.prepend(base.createLoading());
  1814. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  1815. if (res === 'success') {
  1816. $('.listener-rpc-task').show();
  1817. target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow");
  1818. } else {
  1819. target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow");
  1820. }
  1821. });
  1822. doc.on('click', '.listener-send-rpc', (e) => {
  1823. $('.listener-link-rpc').click();
  1824. $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow");
  1825. });
  1826. doc.on('click', '.listener-open-setting', () => {
  1827. base.showSetting();
  1828. });
  1829. doc.on('click', '.listener-open-updatelog', () => {
  1830. base.showUpdateLog();
  1831. });
  1832. doc.on('click', '.listener-rpc-task', () => {
  1833. let rpc = JSON.stringify({
  1834. domain: base.getValue('setting_rpc_domain'),
  1835. port: base.getValue('setting_rpc_port'),
  1836. }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`;
  1837. GM_openInTab(url, {active: true});
  1838. });
  1839. },
  1840.  
  1841. addButton() {
  1842. if (!pt) return;
  1843. let $toolWrap;
  1844. let $button = $(`<div class="tianyi-button pl-button">下载助手<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>`);
  1845. if (pt === 'home') {
  1846. let ins = setInterval(() => {
  1847. $toolWrap = $(pan.btn.home);
  1848. if ($toolWrap.length > 0) {
  1849. $toolWrap.prepend($button);
  1850. clearInterval(ins);
  1851. }
  1852. }, 50);
  1853. }
  1854. if (pt === 'share') {
  1855. let ins = setInterval(() => {
  1856. $toolWrap = $(pan.btn.share);
  1857. if ($toolWrap.length > 0) {
  1858. $toolWrap.prepend($button);
  1859. clearInterval(ins);
  1860. }
  1861. }, 50);
  1862. }
  1863. base.createDownloadIframe();
  1864. this.addPageListener();
  1865. },
  1866.  
  1867. addInitButton() {
  1868. if (!pt) return;
  1869. let $toolWrap;
  1870. let $button = $(`<div class="tianyi-button pl-button-init">下载助手(未点亮)</div>`);
  1871. if (pt === 'home') {
  1872. let ins = setInterval(() => {
  1873. $toolWrap = $(pan.btn.home);
  1874. if ($toolWrap.length > 0) {
  1875. $toolWrap.append($button);
  1876. clearInterval(ins);
  1877. }
  1878. }, 50);
  1879. }
  1880. if (pt === 'share') {
  1881. $button.css({'margin-right': '10px'});
  1882. let ins = setInterval(() => {
  1883. $toolWrap = $(pan.btn.share);
  1884. if ($toolWrap.length > 0) {
  1885. $toolWrap.prepend($button);
  1886. clearInterval(ins);
  1887. }
  1888. }, 50);
  1889. }
  1890. $button.click(() => base.initDialog());
  1891. },
  1892.  
  1893. async getToken() {
  1894. let res = await base.getFinalUrl(pan.pcs[1], {});
  1895. let accessToken = res.match(/accessToken=(\w+)/)?.[1];
  1896. accessToken && base.setStorage('accessToken', accessToken);
  1897. return accessToken;
  1898. },
  1899.  
  1900. async getFileUrlByOnce(item, index, token) {
  1901. try {
  1902. if (item.downloadUrl) return {
  1903. index,
  1904. downloadUrl: item.downloadUrl
  1905. };
  1906. let time = Date.now(),
  1907. fileId = item.fileId,
  1908. o = "AccessToken=" + token + "&Timestamp=" + time + "&fileId=" + fileId,
  1909. url = pan.pcs[2] + '?fileId=' + fileId;
  1910. if (item.shareId) {
  1911. o = "AccessToken=" + token + "&Timestamp=" + time + "&dt=1&fileId=" + fileId + "&shareId=" + item.shareId;
  1912. url += '&dt=1&shareId=' + item.shareId;
  1913. }
  1914. let sign = md5(o).toString();
  1915. let res = await base.get(url, {
  1916. "accept": "application/json;charset=UTF-8",
  1917. "sign-type": 1,
  1918. "accesstoken": token,
  1919. "timestamp": time,
  1920. "signature": sign
  1921. });
  1922. if (res.res_code === 0) {
  1923. return {
  1924. index,
  1925. downloadUrl: res.fileDownloadUrl
  1926. };
  1927. } else if (res.errorCode === 'InvalidSessionKey') {
  1928. return {
  1929. index,
  1930. downloadUrl: '提示:请先登录网盘!'
  1931. };
  1932. } else if (res.res_code === 'ShareNotFoundFlatDir') {
  1933. return {
  1934. index,
  1935. downloadUrl: '提示:请先[转存]文件,👉前往[我的网盘]中下载!'
  1936. };
  1937. } else {
  1938. return {
  1939. index,
  1940. downloadUrl: '获取下载地址失败,请刷新重试!'
  1941. };
  1942. }
  1943. } catch (e) {
  1944. return {
  1945. index,
  1946. downloadUrl: '获取下载地址失败,请刷新重试!'
  1947. };
  1948. }
  1949. },
  1950.  
  1951. async getPCSLink() {
  1952. selectList = this.getSelectedList();
  1953. if (selectList.length === 0) {
  1954. return message.error('提示:请先勾选要下载的文件!');
  1955. }
  1956. if (this.isOnlyFolder()) {
  1957. return message.error('提示:请打开文件夹后勾选文件!');
  1958. }
  1959. let token = base.getStorage('accessToken') || await this.getToken();
  1960. if (!token) {
  1961. return message.error('提示:请先登录网盘!');
  1962. }
  1963. let queue = [];
  1964. selectList.forEach((item, index) => {
  1965. queue.push(this.getFileUrlByOnce(item, index, token));
  1966. });
  1967.  
  1968. const res = await Promise.all(queue);
  1969. res.forEach(val => {
  1970. selectList[val.index].downloadUrl = val.downloadUrl;
  1971. });
  1972.  
  1973. let html = this.generateDom(selectList);
  1974. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  1975. },
  1976.  
  1977. generateDom(list) {
  1978. let content = '<div class="pl-main">';
  1979. let alinkAllText = '';
  1980. list.forEach((v, i) => {
  1981. if (v.isFolder) return;
  1982. let filename = v.fileName;
  1983. let size = base.sizeFormat(v.size);
  1984. let dlink = v.downloadUrl;
  1985. if (mode === 'api') {
  1986. content += `<div class="pl-item">
  1987. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1988. <a class="pl-item-link listener-link-api" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
  1989. </div>`;
  1990. }
  1991. if (mode === 'aria') {
  1992. let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
  1993. alinkAllText += alink + '\r\n';
  1994. content += `<div class="pl-item">
  1995. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  1996. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  1997. }
  1998. if (mode === 'rpc') {
  1999. content += `<div class="pl-item">
  2000. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2001. <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`;
  2002. }
  2003. if (mode === 'curl') {
  2004. let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
  2005. alinkAllText += alink + '\r\n';
  2006. content += `<div class="pl-item">
  2007. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2008. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  2009. }
  2010. if (mode === 'bc') {
  2011. let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
  2012. content += `<div class="pl-item">
  2013. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2014. <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  2015. }
  2016. });
  2017. content += '</div>';
  2018. if (mode === 'aria')
  2019. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;
  2020. if (mode === 'rpc') {
  2021. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  2022. 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>`;
  2023. }
  2024. if (mode === 'curl')
  2025. 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>`;
  2026. return content;
  2027. },
  2028.  
  2029. async sendLinkToRPC(filename, link) {
  2030. let rpc = {
  2031. domain: base.getValue('setting_rpc_domain'),
  2032. port: base.getValue('setting_rpc_port'),
  2033. path: base.getValue('setting_rpc_path'),
  2034. token: base.getValue('setting_rpc_token'),
  2035. dir: base.getValue('setting_rpc_dir'),
  2036. };
  2037.  
  2038. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  2039. let rpcData = {
  2040. id: new Date().getTime(),
  2041. jsonrpc: '2.0',
  2042. method: 'aria2.addUri',
  2043. params: [`token:${rpc.token}`, [link], {
  2044. dir: rpc.dir,
  2045. out: filename,
  2046. header: []
  2047. }]
  2048. };
  2049. try {
  2050. let res = await base.post(url, rpcData, {}, '');
  2051. if (res.result) return 'success';
  2052. return 'fail';
  2053. } catch (e) {
  2054. return 'fail';
  2055. }
  2056. },
  2057.  
  2058. getSelectedList() {
  2059. try {
  2060. return document.querySelector(".c-file-list").__vue__.selectedList;
  2061. } catch (e) {
  2062. return [document.querySelector(".info-detail").__vue__.fileDetail];
  2063. }
  2064. },
  2065.  
  2066. detectPage() {
  2067. let path = location.pathname;
  2068. if (/^\/web\/main/.test(path)) return 'home';
  2069. if (/^\/web\/share/.test(path)) return 'share';
  2070. return '';
  2071. },
  2072.  
  2073. isOnlyFolder() {
  2074. for (let i = 0; i < selectList.length; i++) {
  2075. if (!selectList[i].isFolder) return false;
  2076. }
  2077. return true;
  2078. },
  2079.  
  2080. showMainDialog(title, html, footer) {
  2081. Swal.fire({
  2082. title,
  2083. html,
  2084. footer,
  2085. allowOutsideClick: false,
  2086. showCloseButton: true,
  2087. showConfirmButton: false,
  2088. position: 'top',
  2089. width,
  2090. padding: '15px 20px 5px',
  2091. customClass,
  2092. });
  2093. },
  2094.  
  2095. async initPanLinker() {
  2096. base.initDefaultConfig();
  2097. base.addPanLinkerStyle();
  2098. pt = this.detectPage();
  2099. if (base.getValue('setting_getuser_info') === 'yes') {
  2100. let res = await base.post
  2101. (`https://api.youxiaohou.com/config/tianyi?ver=${version}&a=${author}`, {}, {}, 'text');
  2102. pan = JSON.parse(base.d(res));
  2103. };
  2104. Object.freeze && Object.freeze(pan);
  2105. pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
  2106. this.getToken();
  2107. base.createTip();
  2108. base.registerMenuCommand();
  2109. }
  2110. };
  2111.  
  2112. //迅雷云盘
  2113. let xunlei = {
  2114.  
  2115. convertLinkToAria(link, filename, ua) {
  2116. filename = base.fixFilename(filename);
  2117. return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
  2118. },
  2119.  
  2120. convertLinkToBC(link, filename, ua) {
  2121. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}ZZ`;
  2122. return encodeURIComponent(`bc://http/${base.e(bc)}`);
  2123. },
  2124.  
  2125. convertLinkToCurl(link, filename, ua) {
  2126. let terminal = base.getValue('setting_terminal_type');
  2127. filename = base.fixFilename(filename);
  2128. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}"`);
  2129. },
  2130.  
  2131. addPageListener() {
  2132. doc.on('click', '.pl-button-mode', (e) => {
  2133. mode = e.target.dataset.mode;
  2134. Swal.showLoading();
  2135. this.getPCSLink();
  2136. });
  2137. doc.on('click', '.listener-link-api', async (e) => {
  2138. e.preventDefault();
  2139. $('#downloadIframe').attr('src', e.currentTarget.dataset.link);
  2140. });
  2141. doc.on('click', '.listener-link-api-btn', async (e) => {
  2142. base.setClipboard(e.target.dataset.filename);
  2143. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  2144. });
  2145. doc.on('click', '.listener-link-bc-btn', async (e) => {
  2146. let mirror = base.getMirrorList(e.target.dataset.dlink, pan.mirror);
  2147. base.setClipboard(mirror);
  2148. $(e.target).text('复制成功').animate({opacity: '0.5'}, "slow");
  2149. });
  2150. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  2151. e.preventDefault();
  2152. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  2153. $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow");
  2154. });
  2155. doc.on('click', '.listener-link-rpc', async (e) => {
  2156. let target = $(e.currentTarget);
  2157. target.find('.icon').remove();
  2158. target.find('.pl-loading').remove();
  2159. target.prepend(base.createLoading());
  2160. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  2161. if (res === 'success') {
  2162. $('.listener-rpc-task').show();
  2163. target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow");
  2164. } else {
  2165. target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow");
  2166. }
  2167. });
  2168. doc.on('click', '.listener-send-rpc', (e) => {
  2169. $('.listener-link-rpc').click();
  2170. $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow");
  2171. });
  2172. doc.on('click', '.listener-open-setting', () => {
  2173. base.showSetting();
  2174. });
  2175. doc.on('click', '.listener-open-updatelog', () => {
  2176. base.showUpdateLog();
  2177. });
  2178. doc.on('click', '.listener-rpc-task', () => {
  2179. let rpc = JSON.stringify({
  2180. domain: base.getValue('setting_rpc_domain'),
  2181. port: base.getValue('setting_rpc_port'),
  2182. }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`;
  2183. GM_openInTab(url, {active: true});
  2184. });
  2185. },
  2186.  
  2187. addButton() {
  2188. if (!pt) return;
  2189. let $toolWrap;
  2190. let $button = $(`<div class="xunlei-button pl-button"><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>`);
  2191. if (pt === 'home') {
  2192. let ins = setInterval(() => {
  2193. $toolWrap = $(pan.btn.home);
  2194. if ($toolWrap.length > 0) {
  2195. $toolWrap.prepend($button);
  2196. clearInterval(ins);
  2197. }
  2198. }, 50);
  2199. }
  2200. if (pt === 'share') {
  2201. $button.css({'margin-right': '10px'});
  2202. let ins = setInterval(() => {
  2203. $toolWrap = $(pan.btn.share);
  2204. if ($toolWrap.length > 0) {
  2205. $toolWrap.prepend($button);
  2206. clearInterval(ins);
  2207. }
  2208. }, 50);
  2209. }
  2210. base.createDownloadIframe();
  2211. this.addPageListener();
  2212. },
  2213.  
  2214. addInitButton() {
  2215. if (!pt) return;
  2216. let $toolWrap;
  2217. let $button = $(`<div class="xunlei-button pl-button-init"><i class="xlpfont xlp-download"></i><span style="font-size: 13px;margin-left: 6px;">下载助手(未点亮)</span></div>`);
  2218. if (pt === 'home') {
  2219. let ins = setInterval(() => {
  2220. $toolWrap = $(pan.btn.home);
  2221. if ($toolWrap.length > 0) {
  2222. $toolWrap.append($button);
  2223. clearInterval(ins);
  2224. }
  2225. }, 50);
  2226. }
  2227. if (pt === 'share') {
  2228. $button.css({'margin-right': '10px'});
  2229. let ins = setInterval(() => {
  2230. $toolWrap = $(pan.btn.share);
  2231. if ($toolWrap.length > 0) {
  2232. $toolWrap.prepend($button);
  2233. clearInterval(ins);
  2234. }
  2235. }, 50);
  2236. }
  2237. $button.click(() => base.initDialog());
  2238. },
  2239.  
  2240. getToken() {
  2241. let credentials = {}, captcha = {};
  2242. for (let i = 0; i < localStorage.length; i++) {
  2243. if (/^credentials_/.test(localStorage.key(i))) {
  2244. credentials = base.getStorage(localStorage.key(i));
  2245. base.setStorage('');
  2246. }
  2247. if (/^captcha_[\w]{16}/.test(localStorage.key(i))) {
  2248. captcha = base.getStorage(localStorage.key(i));
  2249. }
  2250. }
  2251. let deviceid = /(\w{32})/.exec(base.getStorage('deviceid').split(','))[0];
  2252. let token = {
  2253. credentials,
  2254. captcha,
  2255. deviceid
  2256. };
  2257. return token;
  2258. },
  2259.  
  2260. async getFileUrlByOnce(item, index, token) {
  2261. try {
  2262. if (item.downloadUrl) return {
  2263. index,
  2264. downloadUrl: item.downloadUrl
  2265. };
  2266. let res = await base.get(pan.pcs[0] + item.id, {
  2267. 'Authorization': `${token.credentials.token_type} ${token.credentials.access_token}`,
  2268. 'content-type': "application/json",
  2269. 'x-captcha-token': token.captcha.token,
  2270. 'x-device-id': token.deviceid,
  2271. });
  2272. if (res.web_content_link) {
  2273. return {
  2274. index,
  2275. downloadUrl: res.web_content_link
  2276. };
  2277. } else {
  2278. return {
  2279. index,
  2280. downloadUrl: '获取下载地址失败,请刷新重试!'
  2281. };
  2282. }
  2283. } catch (e) {
  2284. return message.error('提示:请先登录网盘后刷新页面!');
  2285. }
  2286. },
  2287.  
  2288. async getPCSLink() {
  2289. selectList = this.getSelectedList();
  2290. if (selectList.length === 0) {
  2291. return message.error('提示:请先勾选要下载的文件!');
  2292. }
  2293. if (this.isOnlyFolder()) {
  2294. return message.error('提示:请打开文件夹后勾选文件!');
  2295. }
  2296. if (pt === 'home') {
  2297. let queue = [];
  2298. let token = this.getToken();
  2299. selectList.forEach((item, index) => {
  2300. queue.push(this.getFileUrlByOnce(item, index, token));
  2301. });
  2302. const res = await Promise.all(queue);
  2303. res.forEach(val => {
  2304. selectList[val.index].downloadUrl = val.downloadUrl;
  2305. });
  2306. } else {
  2307. return message.error('提示:请保存到自己网盘后去网盘主页下载!');
  2308. }
  2309. let html = this.generateDom(selectList);
  2310. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  2311.  
  2312. },
  2313.  
  2314. generateDom(list) {
  2315. let content = '<div class="pl-main">';
  2316. let alinkAllText = '';
  2317. list.forEach((v, i) => {
  2318. if (v.kind === 'drive#folder') return;
  2319. let filename = v.name;
  2320. let size = base.sizeFormat(+v.size);
  2321. let dlink = v.downloadUrl;
  2322. if (mode === 'api') {
  2323. content += `<div class="pl-item">
  2324. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2325. <a class="pl-item-link listener-link-api" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
  2326. <div class="pl-item-btn listener-link-api-btn" data-filename="${filename}">复制文件名</div>
  2327. </div>`;
  2328. }
  2329. if (mode === 'aria') {
  2330. let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
  2331. alinkAllText += alink + '\r\n';
  2332. content += `<div class="pl-item">
  2333. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2334. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  2335. }
  2336. if (mode === 'rpc') {
  2337. content += `<div class="pl-item">
  2338. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2339. <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`;
  2340. }
  2341. if (mode === 'curl') {
  2342. let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
  2343. alinkAllText += alink + '\r\n';
  2344. content += `<div class="pl-item">
  2345. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2346. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  2347. }
  2348. if (mode === 'bc') {
  2349. let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
  2350. content += `<div class="pl-item">
  2351. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2352. <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a>
  2353. <div class="pl-item-btn listener-link-bc-btn" data-dlink="${dlink}">复制镜像地址</div>
  2354. </div>`;
  2355. }
  2356. });
  2357. content += '</div>';
  2358. if (mode === 'aria')
  2359. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;
  2360. if (mode === 'rpc') {
  2361. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  2362. 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>`;
  2363. }
  2364. if (mode === 'curl')
  2365. 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>`;
  2366. return content;
  2367. },
  2368.  
  2369. async sendLinkToRPC(filename, link) {
  2370. let rpc = {
  2371. domain: base.getValue('setting_rpc_domain'),
  2372. port: base.getValue('setting_rpc_port'),
  2373. path: base.getValue('setting_rpc_path'),
  2374. token: base.getValue('setting_rpc_token'),
  2375. dir: base.getValue('setting_rpc_dir'),
  2376. };
  2377.  
  2378. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  2379. let rpcData = {
  2380. id: new Date().getTime(),
  2381. jsonrpc: '2.0',
  2382. method: 'aria2.addUri',
  2383. params: [`token:${rpc.token}`, [link], {
  2384. dir: rpc.dir,
  2385. out: filename,
  2386. header: []
  2387. }]
  2388. };
  2389. try {
  2390. let res = await base.post(url, rpcData, {}, '');
  2391. if (res.result) return 'success';
  2392. return 'fail';
  2393. } catch (e) {
  2394. return 'fail';
  2395. }
  2396. },
  2397.  
  2398. getSelectedList() {
  2399. try {
  2400. let doms = document.querySelectorAll('.pan-list-item');
  2401. let selectedList = [];
  2402. for (let dom of doms) {
  2403. let domVue = dom.__vue__;
  2404. if (domVue.selected.includes(domVue.info.id)) {
  2405. selectedList.push(domVue.info);
  2406. }
  2407. }
  2408. return selectedList;
  2409. } catch (e) {
  2410. return [];
  2411. }
  2412. },
  2413.  
  2414. detectPage() {
  2415. let path = location.pathname;
  2416. if (/^\/$/.test(path)) return 'home';
  2417. if (/^\/(s|share)\//.test(path)) return 'share';
  2418. return '';
  2419. },
  2420.  
  2421. isOnlyFolder() {
  2422. for (let i = 0; i < selectList.length; i++) {
  2423. if (selectList[i].kind === 'drive#file') return false;
  2424. }
  2425. return true;
  2426. },
  2427.  
  2428. showMainDialog(title, html, footer) {
  2429. Swal.fire({
  2430. title,
  2431. html,
  2432. footer,
  2433. allowOutsideClick: false,
  2434. showCloseButton: true,
  2435. showConfirmButton: false,
  2436. position: 'top',
  2437. width,
  2438. padding: '15px 20px 5px',
  2439. customClass,
  2440. });
  2441. },
  2442.  
  2443. async initPanLinker() {
  2444. base.initDefaultConfig();
  2445. base.addPanLinkerStyle();
  2446. pt = this.detectPage();
  2447. if (base.getValue('setting_getuser_info') === 'yes') {
  2448. let res = await base.post
  2449. (`https://api.youxiaohou.com/config/xunlei?ver=${version}&a=${author}`, {}, {}, 'text');
  2450. pan = JSON.parse(base.d(res));
  2451. };
  2452. Object.freeze && Object.freeze(pan);
  2453. pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
  2454. base.createTip();
  2455. base.registerMenuCommand();
  2456. }
  2457. };
  2458.  
  2459. //夸克网盘
  2460. let quark = {
  2461.  
  2462. convertLinkToAria(link, filename, ua) {
  2463. filename = base.fixFilename(filename);
  2464. return encodeURIComponent(`aria2c "${link}" --out "${filename}" --header "Cookie: ${document.cookie}"`);
  2465. },
  2466.  
  2467. convertLinkToBC(link, filename, ua) {
  2468. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}&cookie=${encodeURIComponent(document.cookie)}ZZ`;
  2469. return encodeURIComponent(`bc://http/${base.e(bc)}`);
  2470. },
  2471.  
  2472. convertLinkToCurl(link, filename, ua) {
  2473. let terminal = base.getValue('setting_terminal_type');
  2474. filename = base.fixFilename(filename);
  2475. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}" -b "${document.cookie}"`);
  2476. },
  2477.  
  2478. addPageListener() {
  2479. window.addEventListener('hashchange', async (e) => {
  2480. let home = 'https://pan.quark.cn/list#/', all = 'https://pan.quark.cn/list#/list/all';
  2481. if (e.oldURL === home && e.newURL === all) return;
  2482. await base.sleep(150);
  2483. if ($('.quark-button').length > 0) return;
  2484. pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
  2485. });
  2486. doc.on('click', '.pl-button-mode', (e) => {
  2487. mode = e.target.dataset.mode;
  2488. Swal.showLoading();
  2489. this.getPCSLink();
  2490. });
  2491. doc.on('click', '.listener-link-api', async (e) => {
  2492. e.preventDefault();
  2493. $('#downloadIframe').attr('src', e.currentTarget.dataset.link);
  2494. });
  2495. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  2496. e.preventDefault();
  2497. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  2498. $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow");
  2499. });
  2500. doc.on('click', '.listener-link-rpc', async (e) => {
  2501. let target = $(e.currentTarget);
  2502. target.find('.icon').remove();
  2503. target.find('.pl-loading').remove();
  2504. target.prepend(base.createLoading());
  2505. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  2506. if (res === 'success') {
  2507. $('.listener-rpc-task').show();
  2508. target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow");
  2509. } else {
  2510. target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow");
  2511. }
  2512. });
  2513. doc.on('click', '.listener-send-rpc', (e) => {
  2514. $('.listener-link-rpc').click();
  2515. $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow");
  2516. });
  2517. doc.on('click', '.listener-open-setting', () => {
  2518. base.showSetting();
  2519. });
  2520. doc.on('click', '.listener-open-updatelog', () => {
  2521. base.showUpdateLog();
  2522. });
  2523. doc.on('click', '.listener-rpc-task', () => {
  2524. let rpc = JSON.stringify({
  2525. domain: base.getValue('setting_rpc_domain'),
  2526. port: base.getValue('setting_rpc_port'),
  2527. }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`;
  2528. GM_openInTab(url, {active: true});
  2529. });
  2530. },
  2531.  
  2532. addButton() {
  2533. if ($("#quark-button")){
  2534. $("#quark-button").remove();
  2535. };
  2536. if (!pt) return;
  2537. let $toolWrap;
  2538. let $button = $(`<div id="quark-button" class="file-info_r quark-button pl-button"><svg width="22" height="22" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" stroke="#FFFFFF" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 2-2z"/><path d="M14 8h1.553c.85 0 1.16.093 1.47.267.311.174.556.43.722.756.166.326.255.65.255 1.54v4.873c0 .892-.089 1.215-.255 1.54-.166.327-.41.583-.722.757-.31.174-.62.267-1.47.267H6.447c-.85 0-1.16-.093-1.47-.267a1.778 1.778 0 01-.722-.756c-.166-.326-.255-.65-.255-1.54v-4.873c0-.892.089-1.215.255-1.54.166-.327.41-.583.722-.757.31-.174.62-.267 1.47-.267H11"/><path stroke-linecap="round" stroke-linejoin="round" d="M11 3v10"/></g></svg>下载助手<ul class="pl-dropdown-menu"><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>`);
  2539. $button.css({"margin-right":"10px","background-color":color});
  2540. if (pt === 'home') {
  2541. let ins = setInterval(() => {
  2542. $toolWrap = $(pan.btn.home);
  2543. if ($toolWrap.length > 0) {
  2544. $toolWrap.prepend($button);
  2545. clearInterval(ins);
  2546. }
  2547. }, 50);
  2548. }
  2549. if (pt === 'share') {
  2550. $button.css({"margin-right":"10px","background-color":color});
  2551. let ins = setInterval(() => {
  2552. $toolWrap = $(pan.btn.share);
  2553. if ($toolWrap.length > 0) {
  2554. $toolWrap.prepend($button);
  2555. clearInterval(ins);
  2556. }
  2557. }, 50);
  2558. }
  2559. },
  2560.  
  2561. addInitButton() {
  2562. $("#pl-button-init").remove();
  2563. if (!pt) return;
  2564. let $toolWrap;
  2565. let $button = $(`<div id="quark-button" class="file-info_r quark-button pl-button-init"><svg width="22" height="22" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" stroke="#FFFFFF" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 2-2z"/><path d="M14 8h1.553c.85 0 1.16.093 1.47.267.311.174.556.43.722.756.166.326.255.65.255 1.54v4.873c0 .892-.089 1.215-.255 1.54-.166.327-.41.583-.722.757-.31.174-.62.267-1.47.267H6.447c-.85 0-1.16-.093-1.47-.267a1.778 1.778 0 01-.722-.756c-.166-.326-.255-.65-.255-1.54v-4.873c0-.892.089-1.215.255-1.54.166-.327.41-.583.722-.757.31-.174.62-.267 1.47-.267H11"/><path stroke-linecap="round" stroke-linejoin="round" d="M11 3v10"/></g></svg>下载助手(未点亮)</div>`);
  2566. $button.css({"margin-right":"10px","background-color":color});
  2567. if (pt === 'home') {
  2568. let ins = setInterval(() => {
  2569. $toolWrap = $(pan.btn.home);
  2570. if ($toolWrap.length > 0) {
  2571. $toolWrap.prepend($button);
  2572. clearInterval(ins);
  2573. }
  2574. }, 50);
  2575. }
  2576. if (pt === 'share') {
  2577. $button.css({'margin-right': '10px','width': '160px',"background-color":color});
  2578. let ins = setInterval(() => {
  2579. $toolWrap = $(pan.btn.share);
  2580. if ($toolWrap.length > 0) {
  2581. $toolWrap.prepend($button);
  2582. clearInterval(ins);
  2583. }
  2584. }, 50);
  2585. }
  2586. $button.click(() => base.initDialog());
  2587. },
  2588.  
  2589. async getPCSLink() {
  2590. selectList = this.getSelectedList();
  2591. if (selectList.length === 0) {
  2592. return message.error('提示:请先勾选要下载的文件!');
  2593. }
  2594. if (this.isOnlyFolder()) {
  2595. return message.error('提示:请打开文件夹后勾选文件!');
  2596. }
  2597. let fids = [];
  2598. selectList.forEach(val => {
  2599. fids.push(val.fid);
  2600. });
  2601. if (pt === 'home') {
  2602. let res = await base.post(pan.pcs[0], {
  2603. "fids": fids
  2604. }, {"content-type": "application/json;charset=utf-8", "user-agent": pan.ua});
  2605. if (res.code === 31001) {
  2606. return message.error('提示:请先登录网盘!');
  2607. }
  2608. if (res.code !== 0) {
  2609. return message.error('提示:获取链接失败!');
  2610. }
  2611. let html = this.generateDom(res.data);
  2612. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  2613. } else {
  2614. message.error('提示:请保存到自己网盘后去网盘主页下载!');
  2615. await base.sleep(1000);
  2616. document.querySelector('.file-info_r').click();
  2617. return;
  2618. }
  2619. },
  2620.  
  2621. generateDom(list) {
  2622. let content = '<div class="pl-main">';
  2623. let alinkAllText = '';
  2624. list.forEach((v, i) => {
  2625. if (v.file === false) return;
  2626. let filename = v.file_name;
  2627. let fid = v.fid;
  2628. let size = base.sizeFormat(v.size);
  2629. let dlink = v.download_url;
  2630. if (mode === 'api') {
  2631. content += `<div class="pl-item">
  2632. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2633. <a class="pl-item-link listener-link-api" data-fid="${fid}" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
  2634. </div>`;
  2635. }
  2636. if (mode === 'aria') {
  2637. let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
  2638. alinkAllText += alink + '\r\n';
  2639. content += `<div class="pl-item">
  2640. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2641. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  2642. }
  2643. if (mode === 'rpc') {
  2644. content += `<div class="pl-item">
  2645. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2646. <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`;
  2647. }
  2648. if (mode === 'curl') {
  2649. let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
  2650. alinkAllText += alink + '\r\n';
  2651. content += `<div class="pl-item">
  2652. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2653. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  2654. }
  2655. if (mode === 'bc') {
  2656. let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
  2657. content += `<div class="pl-item">
  2658. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  2659. <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  2660. }
  2661. });
  2662. content += '</div>';
  2663. if (mode === 'aria')
  2664. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;
  2665. if (mode === 'rpc') {
  2666. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  2667. 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>`;
  2668. }
  2669. if (mode === 'curl')
  2670. 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>`;
  2671. return content;
  2672. },
  2673.  
  2674. async sendLinkToRPC(filename, link) {
  2675. let rpc = {
  2676. domain: base.getValue('setting_rpc_domain'),
  2677. port: base.getValue('setting_rpc_port'),
  2678. path: base.getValue('setting_rpc_path'),
  2679. token: base.getValue('setting_rpc_token'),
  2680. dir: base.getValue('setting_rpc_dir'),
  2681. };
  2682.  
  2683. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  2684. let rpcData = {
  2685. id: new Date().getTime(),
  2686. jsonrpc: '2.0',
  2687. method: 'aria2.addUri',
  2688. params: [`token:${rpc.token}`, [link], {
  2689. dir: rpc.dir,
  2690. out: filename,
  2691. header: [`Cookie: ${document.cookie}`]
  2692. }]
  2693. };
  2694. try {
  2695. let res = await base.post(url, rpcData, {"Cookie": document.cookie}, '');
  2696. if (res.result) return 'success';
  2697. return 'fail';
  2698. } catch (e) {
  2699. return 'fail';
  2700. }
  2701. },
  2702.  
  2703. getSelectedList() {
  2704. try {
  2705. let selectedList = [];
  2706. let reactDom = document.getElementsByClassName('file-list')[0];
  2707. let reactObj = base.findReact(reactDom);
  2708. let props = reactObj.props;
  2709. if (props) {
  2710. let fileList = props.list || [];
  2711. let selectedKeys = props.selectedRowKeys || [];
  2712. fileList.forEach((val) => {
  2713. if (selectedKeys.includes(val.fid)) {
  2714. selectedList.push(val);
  2715. }
  2716. });
  2717. }
  2718. return selectedList;
  2719. } catch (e) {
  2720. return [];
  2721. }
  2722. },
  2723.  
  2724. detectPage() {
  2725. let path = location.pathname;
  2726. if (/^\/(list)/.test(path)) return 'home';
  2727. if (/^\/(s|share)\//.test(path)) return 'share';
  2728. return '';
  2729. },
  2730.  
  2731. isOnlyFolder() {
  2732. for (let i = 0; i < selectList.length; i++) {
  2733. if (selectList[i].file) return false;
  2734. }
  2735. return true;
  2736. },
  2737.  
  2738. showMainDialog(title, html, footer) {
  2739. Swal.fire({
  2740. title,
  2741. html,
  2742. footer,
  2743. allowOutsideClick: false,
  2744. showCloseButton: true,
  2745. showConfirmButton: false,
  2746. position: 'top',
  2747. width,
  2748. padding: '15px 20px 5px',
  2749. customClass,
  2750. });
  2751. },
  2752.  
  2753. async initPanLinker() {
  2754. base.initDefaultConfig();
  2755. base.addPanLinkerStyle();
  2756. pt = this.detectPage();
  2757. if (base.getValue('setting_getuser_info') === 'yes') {
  2758. let res = await base.post
  2759. (`https://api.youxiaohou.com/config/quark?ver=${version}&a=${author}`, {}, {}, 'text');
  2760. pan = JSON.parse(base.d(res));
  2761. };
  2762. Object.freeze && Object.freeze(pan);
  2763. pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
  2764. this.addPageListener();
  2765. base.createTip();
  2766. base.createDownloadIframe();
  2767. base.registerMenuCommand();
  2768. }
  2769. };
  2770.  
  2771. //中国移动云盘/和彩云
  2772. let yidong = {
  2773.  
  2774. convertLinkToAria(link, filename, ua) {
  2775. filename = base.fixFilename(filename);
  2776. return encodeURIComponent(`aria2c "${link}" --out "${filename}"`);
  2777. },
  2778.  
  2779. convertLinkToBC(link, filename, ua) {
  2780. let bc = `AA/${encodeURIComponent(filename)}/?url=${encodeURIComponent(link)}ZZ`;
  2781. return encodeURIComponent(`bc://http/${base.e(bc)}`);
  2782. },
  2783.  
  2784. convertLinkToCurl(link, filename, ua) {
  2785. let terminal = base.getValue('setting_terminal_type');
  2786. filename = base.fixFilename(filename);
  2787. return encodeURIComponent(`${terminal !== 'wp' ? 'curl' : 'curl.exe'} -L -C - "${link}" -o "${filename}"`);
  2788. },
  2789.  
  2790. addPageListener() {
  2791. doc.on('click', '.pl-button-mode', (e) => {
  2792. mode = e.target.dataset.mode;
  2793. Swal.showLoading();
  2794. this.getPCSLink();
  2795. });
  2796. doc.on('click', '.listener-link-api', async (e) => {
  2797. e.preventDefault();
  2798. $('#downloadIframe').attr('src', e.currentTarget.dataset.link);
  2799. });
  2800. doc.on('click', '.listener-link-aria, .listener-copy-all', (e) => {
  2801. e.preventDefault();
  2802. base.setClipboard(decodeURIComponent(e.target.dataset.link));
  2803. $(e.target).text('复制成功,快去粘贴吧!').animate({opacity: '0.5'}, "slow");
  2804. });
  2805. doc.on('click', '.listener-link-rpc', async (e) => {
  2806. let target = $(e.currentTarget);
  2807. target.find('.icon').remove();
  2808. target.find('.pl-loading').remove();
  2809. target.prepend(base.createLoading());
  2810. let res = await this.sendLinkToRPC(e.currentTarget.dataset.filename, e.currentTarget.dataset.link);
  2811. if (res === 'success') {
  2812. $('.listener-rpc-task').show();
  2813. target.removeClass('pl-btn-danger').html('发送成功,快去看看吧!').animate({opacity: '0.5'}, "slow");
  2814. } else {
  2815. target.addClass('pl-btn-danger').text('发送失败,请检查您的RPC配置信息!').animate({opacity: '0.5'}, "slow");
  2816. }
  2817. });
  2818. doc.on('click', '.listener-send-rpc', (e) => {
  2819. $('.listener-link-rpc').click();
  2820. $(e.target).text('发送完成,发送结果见上方按钮!').animate({opacity: '0.5'}, "slow");
  2821. });
  2822. doc.on('click', '.listener-open-setting', () => {
  2823. base.showSetting();
  2824. });
  2825. doc.on('click', '.listener-open-updatelog', () => {
  2826. base.showUpdateLog();
  2827. });
  2828. doc.on('click', '.listener-rpc-task', () => {
  2829. let rpc = JSON.stringify({
  2830. domain: base.getValue('setting_rpc_domain'),
  2831. port: base.getValue('setting_rpc_port'),
  2832. }), url = `${pan.d}/?rpc=${base.e(rpc)}#${base.getValue('setting_rpc_token')}`;
  2833. GM_openInTab(url, {active: true});
  2834. });
  2835. },
  2836.  
  2837. addButton() {
  2838. if (!pt) return;
  2839. let $toolWrap;
  2840. let $button = $(`<div class="yidong-button pl-button">下载助手<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>${pan.code == 200 && version < pan.version ? pan.new : ''}</ul></div>`);
  2841. if (pt === 'home') {
  2842. let ins = setInterval(() => {
  2843. $toolWrap = $(pan.btn.home);
  2844. if ($toolWrap.length > 0) {
  2845. $toolWrap.prepend($button);
  2846. clearInterval(ins);
  2847. }
  2848. }, 50);
  2849. }
  2850. if (pt === 'share') {
  2851. $button.removeClass('yidong-button').addClass('yidong-share-button');
  2852. let ins = setInterval(() => {
  2853. $toolWrap = $(pan.btn.share);
  2854. if ($toolWrap.length > 0) {
  2855. $toolWrap.prepend($button);
  2856. clearInterval(ins);
  2857. }
  2858. }, 50);
  2859. }
  2860. base.createDownloadIframe();
  2861. this.addPageListener();
  2862. },
  2863.  
  2864. addInitButton() {
  2865. if (!pt) return;
  2866. let $toolWrap;
  2867. let $button = $(`<div class="yidong-button pl-button-init">下载助手(未点亮)</div>`);
  2868. if (pt === 'home') {
  2869. let ins = setInterval(() => {
  2870. $toolWrap = $(pan.btn.home);
  2871. if ($toolWrap.length > 0) {
  2872. $toolWrap.prepend($button);
  2873. clearInterval(ins);
  2874. }
  2875. }, 50);
  2876. }
  2877. if (pt === 'share') {
  2878. $button.removeClass('yidong-button').addClass('yidong-share-button');
  2879. let ins = setInterval(() => {
  2880. $toolWrap = $(pan.btn.share);
  2881. if ($toolWrap.length > 0) {
  2882. $toolWrap.prepend($button);
  2883. clearInterval(ins);
  2884. }
  2885. }, 50);
  2886. }
  2887. $button.click(() => base.initDialog());
  2888. },
  2889.  
  2890. getRandomString(len) {
  2891. len = len || 16;
  2892. let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
  2893. let maxPos = $chars.length;
  2894. let pwd = '';
  2895. for (let i = 0; i < len; i++) {
  2896. pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
  2897. }
  2898. return pwd;
  2899. },
  2900.  
  2901. utob(str) {
  2902. const u = String.fromCharCode;
  2903. return str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g, (t) => {
  2904. if (t.length < 2) {
  2905. let e = t.charCodeAt(0);
  2906. 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);
  2907. }
  2908. e = 65536 + 1024 * (t.charCodeAt(0) - 55296) + (t.charCodeAt(1) - 56320);
  2909. return u(240 | e >>> 18 & 7) + u(128 | e >>> 12 & 63) + u(128 | e >>> 6 & 63) + u(128 | 63 & e);
  2910. });
  2911. },
  2912.  
  2913. getSign(e, t, a, n) {
  2914. let r = "",
  2915. i = "";
  2916. if (t) {
  2917. let s = Object.assign({}, t);
  2918. i = JSON.stringify(s),
  2919. i = i.replace(/\s*/g, ""),
  2920. i = encodeURIComponent(i);
  2921. let c = i.split(""),
  2922. u = c.sort();
  2923. i = u.join("");
  2924. }
  2925. let A = md5(base.e(this.utob(i)));
  2926. let l = md5(a + ":" + n);
  2927. return md5(A + l).toUpperCase();
  2928. },
  2929.  
  2930. async getFileUrlByOnce(item, index) {
  2931. try {
  2932. if (item.downloadUrl) return {
  2933. index,
  2934. downloadUrl: item.downloadUrl
  2935. };
  2936.  
  2937. if (this.detectPage() === 'home') {
  2938. let body = {
  2939. "appName": "",
  2940. "contentID": item.contentID,
  2941. "commonAccountInfo": {"account": item.owner, "accountType": 1}
  2942. };
  2943. let time = new Date(+new Date() + 8 * 3600 * 1000).toJSON().substr(0, 19).replace('T', ' ');
  2944. let key = this.getRandomString(16);
  2945. let sign = this.getSign(undefined, body, time, key);
  2946.  
  2947. let res = await base.post(pan.pcs[0], body, {
  2948. 'x-huawei-channelSrc': '10000034',
  2949. 'x-inner-ntwk': '2',
  2950. 'mcloud-channel': '1000101',
  2951. 'mcloud-client': '10701',
  2952. 'mcloud-sign': time + "," + key + "," + sign,
  2953. 'content-type': "application/json;charset=UTF-8",
  2954. 'caller': 'web',
  2955. 'CMS-DEVICE': 'default',
  2956. 'x-DeviceInfo': '||9|85.0.4183.83|chrome|85.0.4183.83|||windows 10||zh-CN|||',
  2957. 'x-SvcType': '1',
  2958. });
  2959. if (res.success) {
  2960. return {
  2961. index,
  2962. downloadUrl: res.data.downloadURL
  2963. };
  2964. } else {
  2965. return {
  2966. index,
  2967. downloadUrl: '获取下载地址失败,请刷新重试!'
  2968. };
  2969. }
  2970. }
  2971. if (this.detectPage() === 'share') {
  2972. let vueDom = document.querySelector(".home-page").__vue__;
  2973.  
  2974. let res = await base.post(pan.pcs[1], `linkId=${vueDom.linkID}&contentIds=${encodeURIComponent(vueDom.currentPath.id + '/' + item.coID)}&catalogIds=`, {
  2975. 'Content-Type': 'application/x-www-form-urlencoded',
  2976. });
  2977. if (res.code === 0) {
  2978. return {
  2979. index,
  2980. downloadUrl: res.data.redrUrl
  2981. };
  2982. } else {
  2983. return {
  2984. index,
  2985. downloadUrl: '获取下载地址失败,请刷新重试!'
  2986. };
  2987. }
  2988. }
  2989. } catch (e) {
  2990. return {
  2991. index,
  2992. downloadUrl: '获取下载地址失败,请刷新重试!'
  2993. };
  2994. }
  2995. },
  2996.  
  2997. async getPCSLink() {
  2998. selectList = this.getSelectedList();
  2999. if (selectList.length === 0) {
  3000. return message.error('提示:请先勾选要下载的文件!');
  3001. }
  3002. if (this.isOnlyFolder()) {
  3003. return message.error('提示:请打开文件夹后勾选文件!');
  3004. }
  3005.  
  3006. let queue = [];
  3007. selectList.forEach((item, index) => {
  3008. queue.push(this.getFileUrlByOnce(item, index));
  3009. });
  3010.  
  3011. const res = await Promise.all(queue);
  3012. res.forEach(val => {
  3013. selectList[val.index].downloadUrl = val.downloadUrl;
  3014. });
  3015.  
  3016. let html = this.generateDom(selectList);
  3017. this.showMainDialog(pan[mode][0], html, pan[mode][1]);
  3018. },
  3019.  
  3020. generateDom(list) {
  3021. let content = '<div class="pl-main">';
  3022. let alinkAllText = '';
  3023. list.forEach((v, i) => {
  3024. if (v.dirEtag || v.caName) return;
  3025. let filename = v.contentName || v.coName;
  3026. let size = base.sizeFormat(v.contentSize || v.coSize);
  3027. let dlink = v.downloadUrl;
  3028. if (mode === 'api') {
  3029. content += `<div class="pl-item">
  3030. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3031. <a class="pl-item-link listener-link-api" data-filename="${filename}" data-link="${dlink}" data-index="${i}">${dlink}</a>
  3032. </div>`;
  3033. }
  3034. if (mode === 'aria') {
  3035. let alink = this.convertLinkToAria(dlink, filename, navigator.userAgent);
  3036. alinkAllText += alink + '\r\n';
  3037. content += `<div class="pl-item">
  3038. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3039. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制aria2c链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3040. }
  3041. if (mode === 'rpc') {
  3042. content += `<div class="pl-item">
  3043. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3044. <button class="pl-item-link listener-link-rpc pl-btn-primary pl-btn-info" data-filename="${filename}" data-link="${dlink}"><em class="icon icon-device"></em><span style="margin-left: 5px;">推送到 RPC 下载器</span></button></div>`;
  3045. }
  3046. if (mode === 'curl') {
  3047. let alink = this.convertLinkToCurl(dlink, filename, navigator.userAgent);
  3048. alinkAllText += alink + '\r\n';
  3049. content += `<div class="pl-item">
  3050. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3051. <a class="pl-item-link listener-link-aria" href="${alink}" title="点击复制curl链接" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3052. }
  3053. if (mode === 'bc') {
  3054. let alink = this.convertLinkToBC(dlink, filename, navigator.userAgent);
  3055. content += `<div class="pl-item">
  3056. <div class="pl-item-name listener-tip" data-size="${size}">${filename}</div>
  3057. <a class="pl-item-link" href="${decodeURIComponent(alink)}" title="点击用比特彗星下载" data-filename="${filename}" data-link="${alink}">${decodeURIComponent(alink)}</a> </div>`;
  3058. }
  3059. });
  3060. content += '</div>';
  3061. if (mode === 'aria')
  3062. content += `<div class="pl-extra"><button class="pl-btn-primary listener-copy-all" data-link="${alinkAllText}">复制全部链接</button></div>`;
  3063. if (mode === 'rpc') {
  3064. let rpc = base.getValue('setting_rpc_domain') + ':' + base.getValue('setting_rpc_port') + base.getValue('setting_rpc_path');
  3065. 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>`;
  3066. }
  3067. if (mode === 'curl')
  3068. 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>`;
  3069. return content;
  3070. },
  3071.  
  3072. async sendLinkToRPC(filename, link) {
  3073. let rpc = {
  3074. domain: base.getValue('setting_rpc_domain'),
  3075. port: base.getValue('setting_rpc_port'),
  3076. path: base.getValue('setting_rpc_path'),
  3077. token: base.getValue('setting_rpc_token'),
  3078. dir: base.getValue('setting_rpc_dir'),
  3079. };
  3080.  
  3081. let url = `${rpc.domain}:${rpc.port}${rpc.path}`;
  3082. let rpcData = {
  3083. id: new Date().getTime(),
  3084. jsonrpc: '2.0',
  3085. method: 'aria2.addUri',
  3086. params: [`token:${rpc.token}`, [link], {
  3087. dir: rpc.dir,
  3088. out: filename,
  3089. header: []
  3090. }]
  3091. };
  3092. try {
  3093. let res = await base.post(url, rpcData, {}, '');
  3094. if (res.result) return 'success';
  3095. return 'fail';
  3096. } catch (e) {
  3097. return 'fail';
  3098. }
  3099. },
  3100.  
  3101. getSelectedList() {
  3102. try {
  3103. return document.querySelector(".main_file_list").__vue__.selectList.map(val => val.item);
  3104. } catch (e) {
  3105. let vueDom = document.querySelector(".home-page").__vue__;
  3106. let fileList = vueDom._computedWatchers.fileList.value;
  3107. let dirList = vueDom._computedWatchers.dirList.value;
  3108. let selectedFileIndex = vueDom.selectedFile;
  3109. let selectedDirIndex = vueDom.selectedDir;
  3110. let selectFileList = fileList.filter((v, i) => {
  3111. return selectedFileIndex.includes(i);
  3112. });
  3113. let selectDirList = dirList.filter((v, i) => {
  3114. return selectedDirIndex.includes(i);
  3115. });
  3116. return [...selectFileList, ...selectDirList];
  3117. }
  3118. },
  3119.  
  3120. detectPage() {
  3121. let hostname = location.hostname;
  3122. if (/^yun/.test(hostname)) return 'home';
  3123. if (/^caiyun/.test(hostname)) return 'share';
  3124. return '';
  3125. },
  3126.  
  3127. isOnlyFolder() {
  3128. for (let i = 0; i < selectList.length; i++) {
  3129. if (selectList[i].fileEtag || selectList[i].coName) return false;
  3130. }
  3131. return true;
  3132. },
  3133.  
  3134. showMainDialog(title, html, footer) {
  3135. Swal.fire({
  3136. title,
  3137. html,
  3138. footer,
  3139. allowOutsideClick: false,
  3140. showCloseButton: true,
  3141. showConfirmButton: false,
  3142. position: 'top',
  3143. width,
  3144. padding: '15px 20px 5px',
  3145. customClass,
  3146. });
  3147. },
  3148.  
  3149. async initPanLinker() {
  3150. base.initDefaultConfig();
  3151. base.addPanLinkerStyle();
  3152. pt = this.detectPage();
  3153. let res = await base.post
  3154. (`https://api.youxiaohou.com/config/yidong?ver=${version}&a=${author}`, {}, {}, 'text');
  3155. pan = JSON.parse(base.d(res));
  3156. Object.freeze && Object.freeze(pan);
  3157. pan.num === base.getValue('setting_init_code') ? this.addButton() : this.addInitButton();
  3158. base.createTip();
  3159. base.registerMenuCommand();
  3160. }
  3161. };
  3162.  
  3163. let youxiaohou ={
  3164. async initPanLinker() {
  3165. base.initDefaultConfig();
  3166. base.addPanLinkerStyle();
  3167. let res = await base.post
  3168. (`https://api.youxiaohou.com/config/?ver=${version}&a=${author}`, {}, {}, 'text');
  3169. pan = JSON.parse(base.d(res));
  3170. base.createTip();
  3171. base.registerPanMenuCommand();
  3172.  
  3173. let $button1 = `<div class="nav-item" style="text-align: center;"><a class="listener-open-updatelog">(改)下载助手<br>更新日志</a></div>`
  3174. doc.on('click', '.listener-open-updatelog', () => {
  3175. base.showUpdateLog();
  3176. });
  3177. document.getElementsByClassName("nav-links can-hide")[0].innerHTML += $button1
  3178.  
  3179. let $button2 = `<div class="nav-item" style="text-align: center;"><a class="listener-open-info">(改)下载助手<br>暗号查看</a></div>`
  3180. doc.on('click', '.listener-open-info', () => {
  3181. base.showPanInfo();
  3182. });
  3183. document.getElementsByClassName("nav-links can-hide")[0].innerHTML += $button2
  3184. }
  3185. }
  3186.  
  3187. let main = {
  3188. init() {
  3189. if (/(pan|yun).baidu.com/.test(location.host)) {
  3190. baidu.initPanLinker();
  3191. }
  3192. if (/www.aliyundrive.com/.test(location.host)) {
  3193. ali.initPanLinker();
  3194. }
  3195. if (/cloud.189.cn/.test(location.host)) {
  3196. tianyi.initPanLinker();
  3197. }
  3198. if (/pan.xunlei.com/.test(location.host)) {
  3199. xunlei.initPanLinker();
  3200. }
  3201. if (/pan.quark.cn/.test(location.host)) {
  3202. quark.initPanLinker();
  3203. }
  3204. if (/(yun|caiyun).139.com/.test(location.host)) {
  3205. yidong.initPanLinker();
  3206. }
  3207. if (/www.youxiaohou.com/.test(location.host)) {
  3208. youxiaohou.initPanLinker();
  3209. }
  3210. }
  3211. };
  3212.  
  3213. main.init();
  3214. })();