(改)网盘直链下载助手

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

当前为 2023-04-18 提交的版本,查看 最新版本

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