baiduwangpan-cli 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -146,7 +146,7 @@ bdp gtree <gid> [--depth N] [--concurrency N] [--max-nodes N]
146
146
  bdp gsearch <gid> <keyword> 搜索群文件名 (全量遍历目录)
147
147
  [--page N] [--limit N] [--depth N] [--concurrency N]
148
148
  [--max-pages N] [--max-requests N] [--no-unique]
149
- [--all|--all-results] [--timeout N] [--no-cache]
149
+ [--all|--all-results] [--timeout N] [--save-partial] [--no-cache]
150
150
  bdp cache [clear] 查看 / 清空会话缓存 (~/.bdp/cache/)
151
151
  ```
152
152
 
@@ -174,6 +174,7 @@ bdp cache [clear] 查看 / 清空会话缓存 (~/.bdp/cache/)
174
174
  --no-unique 保留不同 msgId 的重复项 (gsearch)
175
175
  --all, --all-results 忽略分页获取全部结果 (gsearch; 不限时, 慢但完整)
176
176
  --timeout <N> 超时秒数,到点返回已扫到的部分结果 (gsearch; 0=不限时, 默认 0)
177
+ --save-partial 未完整时自动把已搜到的结果存为 JSON 并打印路径 (gsearch; 配 --json-file 时写该文件)
177
178
  --no-cache 禁用会话缓存 (gsearch/gtree/gshares/gls)
178
179
  ```
179
180
 
package/bin/bdp.js CHANGED
@@ -34,6 +34,7 @@
34
34
  const { config } = require("../lib");
35
35
  const pan = require("../lib/pan");
36
36
  const group = require("../lib/group");
37
+ const partial = require("../lib/partial");
37
38
 
38
39
  // ── Utils ──────────────────────────────────────────────
39
40
 
@@ -88,6 +89,8 @@ function parseArgs(argv) {
88
89
  opts.flags.timeout = parseInt(argv[++i], 10) || 0;
89
90
  } else if (arg === "--timeout-ms") {
90
91
  opts.flags.timeoutMs = parseInt(argv[++i], 10) || 0;
92
+ } else if (arg === "--save-partial") {
93
+ opts.flags.savePartial = true;
91
94
  } else if (arg === "-n" || arg === "--lines") {
92
95
  opts.flags.n = parseInt(argv[++i], 10) || 20;
93
96
  } else if (arg === "-p" || arg === "--path") {
@@ -487,20 +490,26 @@ cmds.gsearch = async (args, json) => {
487
490
  cache: args.flags.noCache !== true,
488
491
  };
489
492
 
490
- // --json-file:扫描过程中持续写部分结果,即使被外部超时/杀掉,部分结果也已落盘
493
+ // --save-partial:未完整(超时/限流/预算/失败)时自动把已搜到的结果落盘;
494
+ // 未指定 --json-file 时自动生成路径(bdp-gsearch-<gid>-<kw>-partial-<ts>.json)
495
+ const savePartial = args.flags.savePartial === true;
491
496
  const jsonFile = args.flags.jsonFile;
497
+ const partialFile = jsonFile || (savePartial ? partial.defaultPartialFile(gid, keyword) : null);
492
498
  const fsMod = require("fs");
499
+
500
+ // 扫描过程中持续写部分结果(--json-file 或 --save-partial 自动文件),
501
+ // 即使被外部超时/杀掉,已搜到的结果也已落盘
493
502
  let lastProgressWrite = 0;
494
- if (jsonFile) {
495
- fsMod.writeFileSync(jsonFile, JSON.stringify({ running: true, results: [], complete: false, partial: true }, null, 2), "utf-8");
503
+ if (partialFile) {
504
+ fsMod.writeFileSync(partialFile, JSON.stringify({ running: true, results: [], complete: false, partial: true }, null, 2), "utf-8");
496
505
  }
497
506
  opts.onProgress = (snap) => {
498
- if (!jsonFile) return;
507
+ if (!partialFile) return;
499
508
  const now = Date.now();
500
509
  if (snap.running && now - lastProgressWrite < 400) return; // 节流,避免频繁写盘
501
510
  lastProgressWrite = now;
502
511
  fsMod.writeFileSync(
503
- jsonFile,
512
+ partialFile,
504
513
  JSON.stringify(
505
514
  {
506
515
  running: snap.running,
@@ -527,7 +536,7 @@ cmds.gsearch = async (args, json) => {
527
536
  );
528
537
  };
529
538
 
530
- verboseLog(args, `gsearch gid=${gid} keyword="${keyword}" page=${opts.page} limit=${opts.limit} concurrency=${opts.concurrency} unique=${opts.unique} all=${opts.all} timeoutMs=${opts.timeoutMs} depth=${opts.depth} maxPages=${opts.maxPages} maxRequests=${opts.maxRequests} cache=${opts.cache}`);
539
+ verboseLog(args, `gsearch gid=${gid} keyword="${keyword}" page=${opts.page} limit=${opts.limit} concurrency=${opts.concurrency} unique=${opts.unique} all=${opts.all} timeoutMs=${opts.timeoutMs} savePartial=${savePartial} depth=${opts.depth} maxPages=${opts.maxPages} maxRequests=${opts.maxRequests} cache=${opts.cache}`);
531
540
  const result = await group.searchFiles(gid, keyword, opts);
532
541
 
533
542
  if (result.partial) {
@@ -542,10 +551,7 @@ cmds.gsearch = async (args, json) => {
542
551
 
543
552
  if (args.flags.legacyJson) {
544
553
  emitJson(result.results, args);
545
- return;
546
- }
547
-
548
- if (args.flags.jsonFile || json) {
554
+ } else if (args.flags.jsonFile || json) {
549
555
  emitJson(result, args);
550
556
  } else {
551
557
  console.log(`${result.returned} matches for "${keyword}"${result.hasMore ? " (has more — use --page " + (result.nextPage || "?") + ")" : ""}:\n`);
@@ -561,6 +567,21 @@ cmds.gsearch = async (args, json) => {
561
567
  console.error(`[verbose] ${result.failedShares} shares failed (partial result)`);
562
568
  }
563
569
  }
570
+
571
+ // --save-partial:未完整时把已搜到的结果写盘并告知路径(stderr,不污染 JSON stdout)
572
+ if (savePartial && partialFile && result.partial) {
573
+ if (!jsonFile) {
574
+ fsMod.writeFileSync(
575
+ partialFile,
576
+ JSON.stringify(partial.buildPartialPayload(result, { gid, keyword }), null, 2),
577
+ "utf-8"
578
+ );
579
+ }
580
+ console.error(`💾 部分结果已保存: ${partialFile}`);
581
+ } else if (savePartial && partialFile && !result.partial && !jsonFile) {
582
+ // 自动生成的文件且搜索完整 → 清理占位文件,避免留下垃圾
583
+ try { fsMod.unlinkSync(partialFile); } catch {}
584
+ }
564
585
  };
565
586
 
566
587
  cmds.cache = async (args, json) => {
@@ -638,7 +659,7 @@ GROUP CHAT OPERATIONS (群聊)
638
659
  gsearch <gid> <keyword> Search group file names (全量遍历目录, 缓存命中秒回)
639
660
  [--page N] [--limit N] [--depth N] [--concurrency N]
640
661
  [--max-pages N] [--max-requests N] [--no-unique]
641
- [--all|--all-results] [--timeout N] [--no-cache]
662
+ [--all|--all-results] [--timeout N] [--save-partial] [--no-cache]
642
663
  cache [clear] Show cache info or clear session cache
643
664
  error <code> Explain an error code (e.g. -3)
644
665
 
@@ -670,6 +691,7 @@ OPTIONS
670
691
  --no-unique Keep duplicates from different msgId (gsearch)
671
692
  --all, --all-results Fetch all results, no paging (gsearch; slow but never truncates)
672
693
  --timeout <N> Abort after N seconds and return partial results (gsearch; 0=unlimited)
694
+ --save-partial Auto-save partial results to JSON when scan is incomplete (gsearch)
673
695
 
674
696
  EXAMPLES
675
697
  bdp login --bduss abc123 --stoken def456
package/lib/partial.js ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * lib/partial.js — gsearch --save-partial 的纯工具函数
3
+ *
4
+ * 用途:搜索未完整(超时/限流/预算耗尽/失败)时,自动把已搜到的部分结果
5
+ * 落盘到 JSON 文件,避免"跑完了才发现只有 partial:true、结果却没保存"。
6
+ */
7
+
8
+ const path = require("path");
9
+
10
+ // 非法文件名字符(Windows/Linux 通用)
11
+ const ILLEGAL = /[\\/:*?"<>|]/g;
12
+
13
+ /**
14
+ * --save-partial 未指定 --json-file 时的默认保存路径:
15
+ * <cwd>/bdp-gsearch-<gid>-<keyword>-partial-<timestamp>.json
16
+ */
17
+ function defaultPartialFile(gid, keyword, options = {}) {
18
+ const cwd = options.cwd || process.cwd();
19
+ const date = options.date || new Date();
20
+ const safeKw = String(keyword == null ? "" : keyword).replace(ILLEGAL, "_").slice(0, 40) || "search";
21
+ const ts = date.toISOString().replace(/[:.]/g, "-");
22
+ return path.join(cwd, `bdp-gsearch-${String(gid)}-${safeKw}-partial-${ts}.json`);
23
+ }
24
+
25
+ /**
26
+ * 部分结果落盘对象:results 为已搜到的全部匹配(不翻页切片),
27
+ * 附带扫描诊断(scannedShares/totalShares/failedShares/stoppedReason 等),
28
+ * 供 Agent / 用户超时后直接读取。
29
+ */
30
+ function buildPartialPayload(result, meta = {}) {
31
+ return {
32
+ saved: "partial",
33
+ partial: true,
34
+ complete: false,
35
+ timedOut: !!result.timedOut,
36
+ stoppedReason: result.stoppedReason || null,
37
+ gid: meta.gid,
38
+ keyword: meta.keyword,
39
+ page: result.page,
40
+ pageSize: result.pageSize,
41
+ total: result.results.length,
42
+ results: result.results,
43
+ scannedShares: result.scannedShares,
44
+ totalShares: result.totalShares,
45
+ failedShares: result.failedShares,
46
+ throttledShares: result.throttledShares,
47
+ cachedDirs: result.cachedDirs,
48
+ budgetUsed: result.budgetUsed,
49
+ depth: result.depth,
50
+ maxPages: result.maxPages,
51
+ };
52
+ }
53
+
54
+ module.exports = { defaultPartialFile, buildPartialPayload };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "baiduwangpan-cli",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "百度网盘 CLI — 全盘读写 · 免下载读取文件内容 · 群聊文件浏览 (Agent 友好)",
5
5
  "main": "lib/index.js",
6
6
  "bin": {