115 网盘 SHA1 批量导出

从 115 网盘递归导出当前文件夹下所有文件的 SHA1 Hash 值,用于批量校验浏览器下载的文件完整性

  1. // ==UserScript==
  2. // @name 115 网盘 SHA1 批量导出
  3. // @version 1.0.4
  4. // @description 从 115 网盘递归导出当前文件夹下所有文件的 SHA1 Hash 值,用于批量校验浏览器下载的文件完整性
  5. // @author FENGberd
  6. // @match https://115.com/?ct=file&ac=userfile*
  7. // @namespace https://gf.qytechs.cn/en/scripts/400550-115-%E7%BD%91%E7%9B%98-sha1-%E6%89%B9%E9%87%8F%E5%AF%BC%E5%87%BA
  8. // @grant GM_setValue
  9. // @grant GM_getValue
  10. // @grant unsafeWindow
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. const $ = unsafeWindow.jQuery, TOP = unsafeWindow.TOP;
  15.  
  16. const options = (function() {
  17. const opts = {
  18. format: 0,
  19. };
  20. try {
  21. return Object.assign(opts, JSON.parse(GM_getValue('options')) ?? {});
  22. } catch (e) {
  23. console.error(e);
  24. }
  25. return opts;
  26. })();
  27.  
  28. function saveOptions() {
  29. GM_setValue('options', JSON.stringify(options));
  30. }
  31.  
  32. function listFiles(cid, callback, prefix, result, pendingDirs) {
  33. pendingDirs.push(cid);
  34.  
  35. TOP.Core.DataAccess.FileRead.GetFileList({
  36. aid: 1,
  37. cid,
  38. o: 'file_name',
  39. asc: '1',
  40. offset: '0',
  41. show_dir: 1,
  42. limit: '1150',
  43. code: '',
  44. scid: '',
  45. snap: 0,
  46. natsort: 1,
  47. record_open_time: 1,
  48. count_folders: 1,
  49. type: '',
  50. }, function ({ data }) {
  51. for (const item of data) {
  52. if (item.cid != cid) {
  53. listFiles(item.cid, null, prefix + item.n + "/", result, pendingDirs);
  54. } else {
  55. result[prefix + item.n] = item;
  56. }
  57. }
  58. pendingDirs.splice(pendingDirs.indexOf(cid), 1);
  59.  
  60. if (!callback) {
  61. return;
  62. }
  63. const check = setInterval(function () {
  64. if (pendingDirs.length == 0) {
  65. callback(result);
  66. clearInterval(check);
  67. }
  68. }, 100);
  69. });
  70. }
  71.  
  72. $(function () {
  73. const target = $('#js_filter_btn');
  74. if (!target.length) {
  75. return;
  76. }
  77.  
  78. const a = $('<a href="javascript:;" class="button btn-line" hide_status="1"><i class="icon-operate ifo-prop"></i><span>导出 SHA1</span></a>');
  79. a.click(function () {
  80. listFiles(TOP.Main.GetCurWangPanCid(), function (data) {
  81. console.info(data);
  82.  
  83. const content = $('<div class="dialog-input"><textarea id="result" rows="8"></textarea></div><div class="dialog-bottom"><div class="con"><a href="javascript:;" class="button btn-light" data-btn="switch-format">切换格式</a><a href="javascript:;" class="button btn-light" data-btn="copy">复制</a><a href="javascript:;" class="button" data-btn="close">关闭</a></div></div>'), textarea = content.find('#result');
  84.  
  85. const update = () => textarea.val(Object.entries(data).map(([path, r]) => {
  86. switch (options.format) {
  87. case 0:
  88. return `${r.sha} *${path}`;
  89. case 1:
  90. return `${r.sha}|${r.s}|${path}`;
  91. case 2:
  92. return `${r.sha}|${path}`;
  93. case 3:
  94. return `${r.sha} ${path}`;
  95. case 4:
  96. return `#SHA-1 *${r.sha} *${path}`;
  97. }
  98. return '未知格式';
  99. }).join('\n'));
  100. update();
  101.  
  102. content.delegate("[data-btn]", "click", function () {
  103. switch ($(this).attr("data-btn")) {
  104. case "switch-format": {
  105. if (++options.format > 4) {
  106. options.format = 0;
  107. }
  108. saveOptions();
  109.  
  110. update();
  111.  
  112. let formatName = '未知格式';
  113. switch (options.format) {
  114. case 0:
  115. formatName = 'SHA1 *文件路径';
  116. break;
  117. case 1:
  118. formatName = 'SHA1|文件大小|文件路径';
  119. break;
  120. case 2:
  121. formatName = 'SHA1|文件路径';
  122. break;
  123. case 3:
  124. formatName = 'SHA1 文件路径';
  125. break;
  126. case 4:
  127. formatName = '#SHA-1 *SHA1 *文件路径';
  128. break;
  129. }
  130. TOP.Core.MinMessage.Show({
  131. text: "当前格式<br/>" + formatName,
  132. type: "suc",
  133. timeout: 2000
  134. });
  135. break;
  136. }
  137. case "copy":
  138. textarea[0].focus();
  139. textarea[0].select();
  140. console.info(TOP.document.execCommand('copy'));
  141. break;
  142. case "close":
  143. _self.Close();
  144. break;
  145. }
  146. });
  147. const _self = new TOP.Core.DialogBase({ title: `SHA1 列表 (${Object.keys(data).length} 文件)`, content: content });
  148. _self.Open();
  149. }, '', [], []);
  150. });
  151. a.insertAfter(target[0]);
  152. });
  153. })();

QingJ © 2025

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