(改)网盘直链下载助手

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

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

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

QingJ © 2025

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