(改)网盘直链下载助手

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

目前為 2023-04-15 提交的版本,檢視 最新版本

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

QingJ © 2025

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