(改)网盘直链下载助手

可以获取网盘文件真实下载地址。基于【网盘直链下载助手】修改自5.9.4版本,加彩蛋(提示:homo),自用,去推广,修原有BUG,修改界面。

当前为 2022-09-21 提交的版本,查看 最新版本

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