仓库用度盘投稿助手

简易功能增强, 方便仓库投稿用

目前为 2020-04-11 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name 仓库用度盘投稿助手
  3. // @namespace moe.jixun.dupan.galacg
  4. // @version 1.2.1
  5. // @description 简易功能增强, 方便仓库投稿用
  6. // @author Jixun<https://jixun.moe/>
  7. // @include http://pan.baidu.com/disk/home*
  8. // @include http://yun.baidu.com/disk/home*
  9. // @include https://pan.baidu.com/disk/home*
  10. // @include https://yun.baidu.com/disk/home*
  11.  
  12. // @compatible firefox GreaseMonkey (有限)
  13. // @compatible firefox Violentmonkey
  14. // @compatible chrome Violentmonkey
  15.  
  16. // @grant none
  17. // @run-at document-start
  18.  
  19. // ==/UserScript==
  20.  
  21. const isGm = (typeof unsafeWindow !== 'undefined') && (unsafeWindow !== window);
  22. if (isGm) {
  23. const INFO = '[仓库助手]';
  24.  
  25. console.info("%s 以 GreaseMonkey 兼容模式执行。该脚本管理器所遇到的问题不能保证能够修复。", INFO);
  26. unsafeWindow.eval(`;(${entry})();`);
  27. } else {
  28. entry();
  29. }
  30.  
  31. function entry () {
  32. const INFO = '[仓库助手]';
  33.  
  34. var oRequire;
  35. if (window.require) {
  36. console.warn("%s 覆盖方式安装,若无效请强制刷新。", INFO);
  37. oRequire = window.require;
  38. window.require = fakeRequire;
  39. Object.assign(fakeRequire, oRequire);
  40. } else {
  41. console.info("%s 钩子方式安装,若失效请报告。", INFO);
  42. Object.defineProperty(window, 'require', {
  43. set: function (require) {
  44. oRequire = require;
  45. },
  46. get: function () {
  47. return fakeRequire;
  48. }
  49. });
  50. }
  51.  
  52. const __AppId = 250528;
  53. const pluginBlacklist = ['右上角广告位', '网盘APP下载', '满减活动', '会员提醒'];
  54. var _G = {};
  55. // window.__debug_G = _G;
  56.  
  57. function fakeRequire(module) {
  58. // console.info('%s Load module: %s', INFO, module);
  59. if (module == 'disk-system:widget/system/uiRender/menu/listMenu.js') {
  60. if (!_G.injected) {
  61. initScript();
  62. _G.injected = true;
  63. }
  64. } else if (module == 'system-core:pluginHub/register/register.js') {
  65. if (!_G.btnInjected) {
  66. registerPlugin();
  67. _G.btnInjected = true;
  68. }
  69. }
  70. return oRequire.apply(this, arguments);
  71. }
  72.  
  73. function menuInsertAfter(list, name, item, noPush) {
  74. for (var i = 0; i < list.length; i++) {
  75. if (list[i] instanceof Array) {
  76. if (menuInsertAfter(list[i], name, item, true)) {
  77. return;
  78. }
  79. } else if (list[i].title === name) {
  80. i++;
  81. list.splice(i, i, item);
  82. return true;
  83. }
  84. }
  85.  
  86. if (!noPush) list.push(item);
  87. }
  88.  
  89. function initScript() {
  90. // Load module
  91. _G.FaceData = oRequire('system-core:data/faceData.js');
  92. _G.ListInit = oRequire("disk-system:widget/pageModule/list/listInit.js");
  93.  
  94. var fileCtxMenu = _G.FaceData.getData().contextMenu.file;
  95. menuInsertAfter(fileCtxMenu, '分享', {
  96. index: 8,
  97. keyboard: 'u',
  98. title: '自定义分享',
  99. display: isFileChecked,
  100. action: lazyDialog('loadCustomShareDialog')
  101. });
  102.  
  103. fileCtxMenu.forEach(m => {
  104. if (m.index >= 2) {
  105. m.index++;
  106. }
  107. });
  108.  
  109. fileCtxMenu.push({
  110. index: 2, // '删除' 的 index。
  111. keyboard: 'r',
  112. position: 'bottom',
  113. title: '批量重命名',
  114. display: isFileChecked,
  115. action: lazyDialog('loadBatchRenameDialog')
  116. });
  117.  
  118. setTimeout(delayLoad, 200);
  119. delayLoadDuCode();
  120.  
  121. // ESC 将关闭所有漂浮窗口
  122. document.addEventListener('keyup', function(e) {
  123. if (e.keyCode == 0x1b) {
  124. $('.dialog-close').click();
  125. }
  126. }, false);
  127. }
  128.  
  129. function registerPlugin() {
  130. window.define('function-widget:jixun/standard-code.js', function(require, exports, module) {
  131. exports.start = lazyDialog('loadStandardCodeDialog');
  132. });
  133.  
  134. window.manifest = window.manifest.filter(plugin => pluginBlacklist.indexOf(plugin.name) === -1);
  135.  
  136. window.manifest.push({
  137. "name": "标准提取码插件",
  138. "group": "moe.jixun.code",
  139. "version": '1.0',
  140. "type": "1",
  141. "description": "类似于 115 的标准提取码",
  142. "filesType": "*",
  143. "buttons": [{
  144. "index": 2,
  145. "disabled": "none",
  146. "title": "标准提取码",
  147. "buttonStyle": "normal",
  148. "pluginId": "JIXUNSTDCODE",
  149. "position": 'tools'
  150. }],
  151. "preload": false,
  152. "depsFiles": [],
  153. "entranceFile": "function-widget:jixun/standard-code.js",
  154. "pluginId": "JIXUNSTDCODE"
  155. });
  156. }
  157.  
  158. function isFileChecked() {
  159. return _G.ListInit.getCheckedItems().length > 0;
  160. }
  161.  
  162. function lazyDialog(name) {
  163. return function() {
  164. if (_G[name]) {
  165. _G[name]();
  166. } else {
  167. loadDependencies();
  168. _G.Tip.show({
  169. mode: 'loading',
  170. msg: '正在努力加载中 ...'
  171. });
  172. }
  173. };
  174. }
  175.  
  176. function nextId() {
  177. if (!nextId.id) nextId.id = 0;
  178. return nextId.id++;
  179. }
  180.  
  181. function confirmDialog(data) {
  182. loadDependencies();
  183.  
  184. var dialog;
  185. var dialogData = {
  186. id: "confirm-" + nextId(),
  187. show: true,
  188. title: data.title,
  189. body: $('<div style="text-align:center; padding:22px;">').append(data.body),
  190. buttons: [{
  191. name: "confirm",
  192. title: data.sureText || "确定",
  193. type: "big",
  194. color: "blue",
  195. padding: ["50px", "50px"],
  196. click: function() {
  197. if ($.isFunction(data.onSure)) {
  198. data.onSure.apply(this, arguments);
  199. } else {
  200. dialog.hide();
  201. }
  202. }
  203. }, {
  204. name: "cancel",
  205. title: data.cancelText || "取消",
  206. type: "big",
  207. padding: ["50px", "50px"],
  208. click: function() {
  209. if ($.isFunction(data.onCancel)) {
  210. data.onCancel.apply(this, arguments);
  211. } else {
  212. dialog.hide();
  213. }
  214. }
  215. }]
  216. };
  217. if (data.cancel === false) {
  218. dialogData.buttons.pop();
  219. }
  220. dialog = new _G.Dialog(dialogData);
  221. return dialog;
  222. }
  223.  
  224. function delayLoad() {
  225. _G.loadCustomShareDialog = (function() {
  226. var _tplCustomShare = `
  227. <div>
  228. <p>请输入提取码: <input id="jx_shareKey" class="jx-input" style="width: 6em" /></p>
  229. <p id="jx_errmsg" class="jx_c_warn jx_hide">无效的提取码, 脚本将随机生成一个分享代码 :&lt;</p>
  230. </div>
  231. <div class="jx_hide">
  232. <p>分享地址: <input id="jx_shortUrl" class="jx-input" style="width: 20em" readonly /></p>
  233. <p>提取码: <input id="jx_shareCode" class="jx-input" style="width: 5em; text-align: center" readonly /></p>
  234.  
  235. <p style="text-align: left">投稿代码:<br /><textarea readonly id="jx_dlboxCode" class="jx jx-input"></textarea></p>
  236. </div>
  237. `;
  238.  
  239. var dialog, $footer, $key, $tplCustomShare;
  240.  
  241. function showDialog() {
  242. $tplCustomShare = $(_tplCustomShare);
  243. dialog = confirmDialog({
  244. title: '自定义分享',
  245. body: $tplCustomShare,
  246. onSure: function() {
  247. handleConfirm();
  248. dialog.hide();
  249. },
  250. onCancel: function() {
  251. dialog.hide();
  252. },
  253. });
  254.  
  255. $footer = dialog.$dialog.find(_G.Dialog.QUERY.dialogFooter);
  256.  
  257. $key = $('#jx_shareKey', $tplCustomShare)
  258. .blur(function() {
  259. if (!isCodeValid(this.value = this.value.trim())) {
  260. $('#jx_errmsg', $tplCustomShare)
  261. .removeClass('jx_hide');
  262. }
  263. })
  264. .focus(function() {
  265. $('#jx_errmsg', $tplCustomShare)
  266. .addClass('jx_hide');
  267. })
  268. .val(genKey(4));
  269. }
  270.  
  271. function handleConfirm() {
  272. var key = $key.val();
  273. if (!isCodeValid(key)) {
  274. key = genKey(4);
  275. $key.val(key);
  276. }
  277.  
  278. _G.Tip.show({
  279. mode: 'loading',
  280. msg: '正在分享,请稍后 ...',
  281. autoClose: false
  282. });
  283.  
  284. var sharedItems = _G.ListInit.getCheckedItems();
  285. $.ajax({
  286. url: '/share/set?' + $.param({
  287. channel: 'chunlei',
  288. bdstoken: yunData.MYBDSTOKEN,
  289. app_id: __AppId
  290. }),
  291. type: 'POST',
  292. data: {
  293. fid_list: JSON.stringify(sharedItems.map(getFileId)),
  294. schannel: 4,
  295. channel_list: '[]',
  296. pwd: key
  297. },
  298. dataType: 'json'
  299. }).success(function(r) {
  300. _G.Tip.hide();
  301.  
  302. _G.Tip.show({
  303. mode: 'success',
  304. msg: '分享成功!'
  305. });
  306.  
  307. $footer.children('.g-button-blue-large').hide();
  308. $footer.children('.g-button-large').find('.text').text('关闭');
  309.  
  310. let url = r.shorturl ? `${r.shorturl}#${key}` : '很抱歉, 分享失败 :<';
  311. $('#jx_shortUrl', $tplCustomShare).val(url);
  312. $('#jx_shareCode', $tplCustomShare).val(key);
  313.  
  314. $tplCustomShare.toggleClass('jx_hide');
  315.  
  316. var title = fixCode(sharedItems[0].server_filename) + (sharedItems.length == 1 ? '' : ' 等文件');
  317.  
  318. $('#jx_dlboxCode', $tplCustomShare).val(
  319. `[dlbox title="${escapeHtml(title)}" from="浩瀚的宇宙" time="${makeDate(new Date())}" info="提取:${escapeHtml(key)}" link1="度娘|${url}"][/dlbox]]`
  320. );
  321.  
  322. dialog.show();
  323. }).fail(function() {
  324. _G.Tip.hide();
  325.  
  326. _G.Tip.show({
  327. mode: 'failure',
  328. msg: '网络错误,请稍后重试。'
  329. });
  330. });
  331. }
  332.  
  333. /* 依赖函数表 */
  334. function isCodeValid(code) {
  335. return encodeURIComponent(code).replace(/%[A-F\d]{2}/g, '-').length == 4;
  336. }
  337.  
  338. function fixCode(code) {
  339. return code.replace(/"/g, '&#x22;').replace(/\]/g, '&#x5D;');
  340. }
  341.  
  342. function fixWidthDigits(d) {
  343. return ('0' + d.toString()).slice(-2);
  344. }
  345.  
  346. function makeDate(d) {
  347. return `${d.getFullYear()}.${fixWidthDigits(d.getMonth() + 1)}.${fixWidthDigits(d.getDate())}`;
  348. }
  349.  
  350. function genKey(size) {
  351. // length => 26 + 10, 36
  352. var keySet = 'abcdefghijklmnopqrstuvwxyz0123456789';
  353. for (var i = (size || 4) | 0, r = ''; i--;)
  354. r += keySet[0 | (Math.random() * 36)];
  355.  
  356. return r;
  357. }
  358.  
  359. function getFileId(item) {
  360. return item.fs_id;
  361. }
  362.  
  363. /* 收尾 */
  364. return showDialog;
  365. })();
  366.  
  367. _G.loadBatchRenameDialog = (function() {
  368. var _tplConfirmRename = `
  369. <p>请输入新的命名规则 (自动储存): <input id="jx_nameRule" class="jx-input" style="width:20em" /></p>
  370. <p style="line-height: 1; padding-top: 1em;">
  371. <code>:n</code> 表示不带扩展名的文件名; <code>:e</code> 表示扩展名; <code>:E</code> 表示 .扩展名;
  372. <br><code>:d</code> 表示一位随机数字; <code>:c</code> 表示一位随机字符; <code>:t</code> 表示当前时间戳</p>
  373. `;
  374.  
  375. var dialog, $tplConfirmRename;
  376.  
  377. function showDialog() {
  378. $tplConfirmRename = $(_tplConfirmRename);
  379. $('#jx_nameRule', $tplConfirmRename).val(localStorage.jxRenameRule || '[GalACG] :d:d:d:d:d:d:d:d:d:d:E');
  380.  
  381. dialog = confirmDialog({
  382. title: '确认批量重命名',
  383. body: $tplConfirmRename,
  384. onSure: function() {
  385. handleConfirm();
  386. dialog.hide();
  387. },
  388. onCancel: function() {
  389. dialog.hide();
  390. },
  391. });
  392. }
  393.  
  394. function handleConfirm() {
  395. // 储存批量重命名记录
  396. var _nameRule = $('#jx_nameRule', $tplConfirmRename).val();
  397. localStorage.jxRenameRule = _nameRule;
  398.  
  399. var _flist = _G.ListInit.getCheckedItems().map(toReplacePayload);
  400.  
  401. _G.Tip.show({
  402. mode: 'loading',
  403. msg: '正在批量重命名,请稍后 ...',
  404. autoClose: false
  405. });
  406.  
  407. $.ajax({
  408. url: '/api/filemanager?' + $.param({
  409. channel: 'chunlei',
  410. bdstoken: yunData.MYBDSTOKEN,
  411. app_id: __AppId,
  412. opera: 'rename'
  413. }),
  414. type: 'POST',
  415. data: {
  416. filelist: JSON.stringify(_flist)
  417. }
  418. }).success(function() {
  419. _G.Tip.hide();
  420. _G.Message.trigger('system-refresh');
  421. }).fail(function() {
  422. _G.Tip.hide();
  423.  
  424. _G.Tip.show({
  425. mode: 'failure',
  426. msg: '批量重命名失败, 请稍后重试!'
  427. });
  428. });
  429.  
  430. function toReplacePayload(item) {
  431. return {
  432. path: item.path,
  433. newname: _nameRule.replace(/:([cdeEn])/g, fixName.bind(item.server_filename))
  434. };
  435. }
  436. }
  437.  
  438. /* 依赖函数表 */
  439. function fixName(z, code) {
  440. switch (code) {
  441. case 'n':
  442. var name = this.match(/^(.+)\./);
  443. return name ? name[1] : this;
  444. case 'c':
  445. return String.fromCharCode(97 + Math.random() * 26);
  446. case 'd':
  447. return Math.random().toString().slice(3, 4);
  448. case 't':
  449. return +new Date();
  450. case 'e':
  451. var ext = this.match(/\.([^.]+)$/);
  452. return ext ? ext[1] : '';
  453. case 'E':
  454. return this.match(/\.[^.]+$/) || '';
  455. }
  456. }
  457.  
  458. /* 收尾 */
  459. return showDialog;
  460. })();
  461. }
  462.  
  463. let div = document.createElement('a');
  464. let escapeDict = {
  465. '"': 'quot',
  466. "'": 'apos',
  467. };
  468. function escapeHtml(text) {
  469. div.textContent = text;
  470. const result = div.innerHTML.replace(/["']/g, x => `&${escapeDict[x]};`);
  471. div.textContent = '';
  472. return result;
  473. }
  474.  
  475. function parseSize(size) {
  476. // 超过 GB
  477. if (size.length > 9) {
  478. size = size.slice(0, -7);
  479. return size.slice(0, -2) + '.' + size.slice(-2) + ' GB';
  480. }
  481.  
  482. return (parseInt(size) / 1024 / 1024).toFixed(2) + ' MB';
  483. }
  484.  
  485. function itemInfo(item) {
  486. const name = escapeHtml(item.name);
  487. return `
  488. <span class="name" title="${name}">${name}</span>
  489. <span class="size">(${escapeHtml(parseSize(item.size))})</span>
  490. `;
  491. }
  492.  
  493. function delayLoadDuCode() {
  494. _G.loadStandardCodeDialog = delayLoadDuStdCode();
  495.  
  496. function delayLoadDuStdCode() {
  497. var _tplStandardCode = `
  498. <div>
  499. <p><textarea class="jx jx_code jx-input" rows="7" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea></p>
  500. <p style="line-height: 1; padding: .5em 0;">
  501. 扩展阅读:
  502. <a href="http://game.ali213.net/thread-5465798-1-1.html" target="_blank">肚娘代码说明 [游侠]</a>
  503. | <a href="https://jixun.moe/2017/06/13/du-code-gen/" target="_blank">标准度娘提取码 [梦姬]</a>
  504. </p>
  505. <p style="text-align:left">
  506. <b>文件列表</b> (版本: <span class="jx_version" style="color:black">--</span>):
  507. </p>
  508. <ul class="jx_list"></ul>
  509. <p class="jx_c_warn jx_hide jx_errmsg">无效的提取码! 请确保您输入的提取码无误。</p>
  510. </div>
  511. `;
  512.  
  513. var dialog, $tplStandardCode, codeInfo, jx_list, jx_code, jx_errmsg, jx_version;
  514. var failed = 0;
  515.  
  516. function showDialog() {
  517. $tplStandardCode = $(_tplStandardCode);
  518.  
  519. dialog = confirmDialog({
  520. title: '通用提取码',
  521. body: $tplStandardCode,
  522. onSure: function() {
  523. handleConfirm();
  524. dialog.hide();
  525. },
  526. onCancel: function() {
  527. dialog.hide();
  528. },
  529. });
  530.  
  531. jx_list = $('.jx_list', $tplStandardCode);
  532. jx_code = $('.jx_code', $tplStandardCode);
  533. jx_errmsg = $('.jx_errmsg', $tplStandardCode);
  534. jx_version = $('.jx_version', $tplStandardCode);
  535.  
  536. function updatePreview () {
  537. var code = jx_code.val();
  538. codeInfo = DuParser.parse(code);
  539. jx_errmsg.toggleClass('jx_hide', Boolean(!code || codeInfo.length));
  540. if (codeInfo.length) {
  541. jx_version.text(codeInfo.ver);
  542. jx_list.html(codeInfo.map(itemInfo).map(x => `<li>${x}</li>`).join(''));
  543. } else {
  544. jx_version.text('--');
  545. jx_list.text('');
  546. }
  547. }
  548. const debounce = fn => {
  549. let timer;
  550. return () => {
  551. cancelAnimationFrame(timer);
  552. timer = requestAnimationFrame(fn);
  553. };
  554. };
  555.  
  556. jx_code.on('blur input', debounce(updatePreview)).focus(function() {
  557. jx_errmsg.addClass('jx_hide');
  558. });
  559. }
  560.  
  561. var _curDir;
  562.  
  563. function handleConfirm() {
  564. _curDir = _G.ListInit.currentKey;
  565. if (_curDir.slice(-1) != '/')
  566. _curDir += '/';
  567.  
  568. failed = 0;
  569. saveFile(0);
  570. }
  571. function statusHtml(success) {
  572. const text = success ? '成功' : '失败';
  573. const className = success ? 'success' : 'fail';
  574. return `<span class="jx-status jx-status-${className}">${text}</span>`;
  575. }
  576.  
  577. function saveFile(i) {
  578. if (i >= codeInfo.length) {
  579. _G.Message.trigger('system-refresh');
  580. const dialog = confirmDialog({
  581. title: `转存完毕 (失败 ${failed} 个, ${i} 个)!`,
  582. body: `
  583. <ul class="save-complete-details jx_list">
  584. ${codeInfo.map(info => `<li>${itemInfo(info)}${statusHtml(info.success)}</li>`).join('')}
  585. </ul>
  586. `,
  587. onSure: function() {
  588. dialog.hide();
  589. },
  590. cancel: false,
  591. });
  592. return;
  593. }
  594.  
  595. _G.Tip.show({
  596. mode: 'loading',
  597. msg: `正在转存文件 (${ i + 1 }/${ codeInfo.length }), 请稍后 ..`,
  598. autoClose: false
  599. });
  600.  
  601. var file = codeInfo[i];
  602.  
  603. $.ajax({
  604. url: '/api/rapidupload?rtype=1',
  605. type: 'POST',
  606. data: {
  607. path: _curDir + file.name,
  608. 'content-md5': file.md5,
  609. 'slice-md5': file.md5s,
  610. 'content-length': file.size,
  611. 'local_mtime': ''
  612. }
  613. }).success(function(r) {
  614. _G.Tip.hide();
  615. if (r.errno) {
  616. failed++;
  617. } else {
  618. codeInfo[i].success = true;
  619. }
  620. }).fail(function(r) {
  621. failed++;
  622. }).always(function() {
  623. saveFile(i + 1);
  624. });
  625. }
  626.  
  627. /**
  628. * 一个简单的类似于 NodeJS Buffer 的实现.
  629. * 用于解析游侠度娘提取码。
  630. * @param {SimpleBuffer}
  631. */
  632. function SimpleBuffer(str) {
  633. this.fromString(str);
  634. }
  635.  
  636. SimpleBuffer.toStdHex = function toStdHex(n) {
  637. return ('0' + n.toString(16)).slice(-2);
  638. };
  639.  
  640. SimpleBuffer.prototype.fromString = function fromString(str) {
  641. var len = str.length;
  642.  
  643. this.buf = new Uint8Array(len);
  644. for (var i = 0; i < len; i++) {
  645. this.buf[i] = str.charCodeAt(i);
  646. }
  647. };
  648.  
  649. SimpleBuffer.prototype.readUnicode = function readUnicode(index, size) {
  650. if (size & 1)
  651. size++;
  652.  
  653. var bufText = Array.prototype.slice.call(this.buf, index, index + size).map(SimpleBuffer.toStdHex);
  654.  
  655. var buf = [''];
  656. for (var i = 0; i < size; i += 2)
  657. buf.push(bufText[i + 1] + bufText[i]);
  658.  
  659. return JSON.parse('"' + buf.join('\\u') + '"');
  660. };
  661.  
  662. SimpleBuffer.prototype.readNumber = function readNumber(index, size) {
  663. var ret = 0;
  664.  
  665. for (var i = index + size; i > index;)
  666. ret = this.buf[--i] + (ret * 256);
  667.  
  668. return ret;
  669. };
  670.  
  671. SimpleBuffer.prototype.readUInt = function readUInt(index) {
  672. return this.readNumber(index, 4);
  673. };
  674.  
  675. SimpleBuffer.prototype.readULong = function readULong(index) {
  676. return this.readNumber(index, 8);
  677. };
  678.  
  679. SimpleBuffer.prototype.readHex = function readHex(index, size) {
  680. return Array.prototype.slice.call(this.buf, index, index + size).map(SimpleBuffer.toStdHex).join('');
  681. };
  682.  
  683. function DuParser() {}
  684. DuParser.parse = function generalDuCodeParse(szUrl) {
  685. var r;
  686. if (szUrl.indexOf('BDLINK') === 0) {
  687. r = DuParser.parseDu_v1(szUrl);
  688. r.ver = '游侠 v1';
  689. } else if (szUrl.indexOf('bdpan://') === 0) {
  690. r = DuParser.parseDu_bdpan(szUrl);
  691. r.ver = 'PanDownload';
  692. } else {
  693. r = DuParser.parseDu_v2(szUrl);
  694. r.ver = '梦姬标准';
  695. }
  696. return r;
  697. };
  698.  
  699. DuParser.parseDu_v1 = function parseDu_v1(szUrl) {
  700. var raw = atob(szUrl.slice(6).replace(/\s/g, ''));
  701. if (raw.slice(0, 5) !== 'BDFS\x00')
  702. return null;
  703.  
  704. var buf = new SimpleBuffer(raw);
  705.  
  706. var ptr = 9;
  707. var arrFiles = [];
  708. var fileInfo, nameSize;
  709. var total = buf.readUInt(5);
  710.  
  711. for (i = 0; i < total; i++) {
  712. // 大小 (8 bytes)
  713. // MD5 + MD5S (0x20)
  714. // nameSize (4 bytes)
  715. // Name (unicode)
  716. fileInfo = {};
  717. fileInfo.size = buf.readULong(ptr + 0);
  718. fileInfo.md5 = buf.readHex(ptr + 8, 0x10);
  719. fileInfo.md5s = buf.readHex(ptr + 0x18, 0x10);
  720. nameSize = buf.readUInt(ptr + 0x28) << 1;
  721. fileInfo.nameSize = nameSize;
  722. ptr += 0x2C;
  723.  
  724. fileInfo.name = buf.readUnicode(ptr, nameSize);
  725. arrFiles.push(fileInfo);
  726. ptr += nameSize;
  727. }
  728.  
  729. return arrFiles;
  730. };
  731.  
  732. DuParser.parseDu_v2 = function parseDu_v2(szUrl) {
  733. return szUrl.split('\n').map(function(z) {
  734. // unsigned long long: 0~18446744073709551615
  735. return z.trim().match(/([\dA-F]{32})#([\dA-F]{32})#([\d]{1,20})#([\s\S]+)/);
  736. }).filter(function(z) {
  737. return z;
  738. }).map(function(info) {
  739. return {
  740. md5: info[1],
  741. md5s: info[2],
  742. size: info[3],
  743. name: info[4]
  744. };
  745. });
  746. };
  747.  
  748. DuParser.parseDu_bdpan = function parseDu_bdpan(szUrl) {
  749. return szUrl.split('\n').map(z => z.trim()).filter(url => szUrl.indexOf('bdpan://') === 0).map(z => {
  750. return atob(z.slice('bdpan://'.length)).trim().match(/^([\s\S]+)\|([\d]{1,20})\|([\dA-F]{32})\|([\dA-F]{32})$/i);
  751. }).filter(function(z) {
  752. return z;
  753. }).map(function([, name, size, md5, md5s]) {
  754. name = decodeURIComponent(name.split('').map(z => `%${('0' + z.charCodeAt(0).toString(16)).slice(-2)}`).join(''));
  755. return { name, size, md5, md5s };
  756. });
  757. };
  758.  
  759. /* 收尾 */
  760. return showDialog;
  761. }
  762. }
  763.  
  764. function loadDependencies() {
  765. _G.Message = oRequire("system-core:system/baseService/message/message.js");
  766. _G.Tip = oRequire("system-core:system/uiService/tip/tip.js");
  767. _G.Dialog = oRequire("system-core:system/uiService/dialog/dialog.js");
  768. _G.Context = oRequire("system-core:context/context.js").instanceForSystem;
  769. _G.ui = _G.Context.ui;
  770. }
  771. };
  772.  
  773. // Inject style
  774. var style = document.createElement('style');
  775. style.textContent = `
  776. .jx_btn {
  777. background: #fefefe;
  778. background: linear-gradient(to bottom, #fefefe 0%,#f2f2f2 88%);
  779.  
  780. display: inline-block;
  781. line-height: 25px;
  782. vertical-align: middle;
  783. margin: 0 0 0 10px;
  784. text-decoration: none;
  785. border: 1px solid #AAA;
  786. padding: 0px 20px;
  787. height: 26px;
  788. border-radius: 2px;
  789.  
  790. min-width: 3em;
  791. text-align: center;
  792. }
  793. .jx_btn, .jx_btn:hover, .jx_btn:focus {
  794. color: #666;
  795. }
  796. .jx_btn:active {
  797. color: #06C;
  798. background: #e3e3e3;
  799. background: -moz-linear-gradient(top, #e3e3e3 0%, #f7f7f7 12%);
  800. background: -webkit-linear-gradient(top, #e3e3e3 0%,#f7f7f7 12%);
  801. background: linear-gradient(to bottom, #e3e3e3 0%,#f7f7f7 12%);
  802. }
  803. .jx-input {
  804. margin: 9px 0;
  805. _margin: 7px 0;
  806. padding: 0 0 0 5px;
  807. width: 200px;
  808. height: 24px;
  809. vertical-align: middle;
  810. border: 1px solid #3b8cff;
  811. border: 1px solid rgba(58,140,255,.3);
  812. background: #fff;
  813. border-radius: 2px;
  814. }
  815.  
  816. .jx_hide { display: none }
  817. .jx_c_warn { color: red }
  818.  
  819. .jx_list {
  820. text-align: left;
  821. max-height: 5.5em;
  822. overflow-y: scroll;
  823. overflow-x: hidden;
  824. line-height: 1;
  825. padding: .2em;
  826. margin-bottom: .5em;
  827. }
  828.  
  829. /*
  830. .jx_list:not(:empty) {
  831. border: 1px solid #ddd;
  832. }
  833. */
  834.  
  835. .jx_list > li {
  836. display: flex;
  837. white-space: nowrap;
  838. line-height: 1.3;
  839. }
  840.  
  841. .jx_list .name {
  842. color: black;
  843.  
  844. overflow: hidden;
  845. text-overflow: ellipsis;
  846. }
  847.  
  848. .jx_list .size {
  849. color: #777;
  850.  
  851. flex-grow: 1;
  852. }
  853.  
  854. .save-complete-details {
  855. max-height: 30em;
  856. }
  857.  
  858. .jx-status {
  859. padding-left: 0.25em;
  860. }
  861.  
  862. .jx-status-success {
  863. color: green;
  864. }
  865.  
  866. .jx-status-fail {
  867. color: red;
  868. }
  869.  
  870. textarea.jx{
  871. width: 100%;
  872. min-height: 5em;
  873. line-height: 1;
  874. }
  875. `;
  876.  
  877. document.head.appendChild(style);

QingJ © 2025

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