tt-help-cli-ycl 1.4.68 → 1.4.70

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tt-help-cli-ycl",
3
- "version": "1.4.68",
3
+ "version": "1.4.70",
4
4
  "description": "TikTok user & video data scraper - extract ttSeller, verified, locationCreated from HTML source",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli/auto.js CHANGED
@@ -5,7 +5,10 @@ import {
5
5
  } from "../lib/browser/page.js";
6
6
  import { userId as configuredUserId, saveUserId } from "../lib/constants.js";
7
7
  import { getMacOrUuid } from "../lib/mac-or-uuid.js";
8
- import { ensureBrowserReady as ensureBrowserReadyCDP } from "../lib/browser/cdp.js";
8
+ import {
9
+ ensureBrowserReady as ensureBrowserReadyCDP,
10
+ killEdgeProcesses,
11
+ } from "../lib/browser/cdp.js";
9
12
  import { createApiClient } from "../lib/api-client.js";
10
13
 
11
14
  const MAX_RETRY_WAIT = 5 * 60 * 1000;
@@ -47,6 +50,8 @@ export async function handleAuto(options) {
47
50
  if (shuttingDown) return;
48
51
  shuttingDown = true;
49
52
  console.error(`\n[Auto] 收到 ${signal},正在关闭浏览器...`);
53
+ // 先杀死 Edge 进程(CDP 模式下 browser.close() 只断开连接,不杀进程)
54
+ await killEdgeProcesses();
50
55
  await browser?.close().catch(() => {});
51
56
  console.error("[Auto] 已退出");
52
57
  process.exit(0);
@@ -20,6 +20,7 @@ import {
20
20
  import { getMacOrUuid } from "../lib/mac-or-uuid.js";
21
21
  import {
22
22
  ensureBrowserReady as ensureBrowserReadyCDP,
23
+ killEdgeProcesses,
23
24
  switchAccount,
24
25
  } from "../lib/browser/cdp.js";
25
26
  import { showResourceUsage } from "../utils/index.js";
@@ -73,12 +74,17 @@ export async function handleExplore(options) {
73
74
 
74
75
  let userId = exploreUserId || configuredUserId;
75
76
  let browser = null;
77
+ let cdpOptions = null;
76
78
  let shuttingDown = false;
77
79
 
78
80
  const shutdown = async (signal) => {
79
81
  if (shuttingDown) return;
80
82
  shuttingDown = true;
81
83
  console.error(`\n[Explore] 收到 ${signal},正在关闭浏览器...`);
84
+ // 先杀死 Edge 进程(CDP 模式下 browser.close() 只断开连接,不杀进程)
85
+ if (cdpOptions) {
86
+ await killEdgeProcesses(cdpOptions.userDataDir, cdpOptions.port);
87
+ }
82
88
  await browser?.close().catch(() => {});
83
89
  console.error("[Explore] 已退出");
84
90
  process.exit(0);
@@ -117,7 +123,7 @@ export async function handleExplore(options) {
117
123
  });
118
124
  let currentAccount = healthChecker.getCurrentAccount();
119
125
 
120
- const cdpOptions = {};
126
+ cdpOptions = {};
121
127
  if (explorePort) {
122
128
  // 固定端口模式(调试用,关闭自动轮换)
123
129
  cdpOptions.port = explorePort;
@@ -20,6 +20,7 @@ import {
20
20
  import { getMacOrUuid } from "../lib/mac-or-uuid.js";
21
21
  import {
22
22
  ensureBrowserReady as ensureBrowserReadyCDP,
23
+ killEdgeProcesses,
23
24
  switchAccount,
24
25
  } from "../lib/browser/cdp.js";
25
26
  import { HealthChecker } from "../lib/browser/health-checker.js";
@@ -72,12 +73,17 @@ export async function handleRefresh(options) {
72
73
 
73
74
  let userId = exploreUserId || configuredUserId;
74
75
  let browser = null;
76
+ let cdpOptions = null;
75
77
  let shuttingDown = false;
76
78
 
77
79
  const shutdown = async (signal) => {
78
80
  if (shuttingDown) return;
79
81
  shuttingDown = true;
80
82
  console.error(`\n[Refresh] 收到 ${signal},正在关闭浏览器...`);
83
+ // 先杀死 Edge 进程(CDP 模式下 browser.close() 只断开连接,不杀进程)
84
+ if (cdpOptions) {
85
+ await killEdgeProcesses(cdpOptions.userDataDir, cdpOptions.port);
86
+ }
81
87
  await browser?.close().catch(() => {});
82
88
  console.error("[Refresh] 已退出");
83
89
  process.exit(0);
@@ -124,7 +130,7 @@ export async function handleRefresh(options) {
124
130
  });
125
131
  let currentAccount = healthChecker.getCurrentAccount();
126
132
 
127
- const cdpOptions = {};
133
+ cdpOptions = {};
128
134
  if (explorePort) {
129
135
  cdpOptions.port = explorePort;
130
136
  cdpOptions.userDataDir = path.join(
@@ -1344,6 +1344,11 @@ function showMainPage() {
1344
1344
  document.getElementById("targetPage").classList.remove("active");
1345
1345
  document.getElementById("tagsPage").classList.remove("active");
1346
1346
  document.getElementById("settingsPage").classList.remove("active");
1347
+ document.getElementById("watchdogPage").classList.remove("active");
1348
+ if (_wdRefreshTimer) {
1349
+ clearInterval(_wdRefreshTimer);
1350
+ _wdRefreshTimer = null;
1351
+ }
1347
1352
  }
1348
1353
 
1349
1354
  function navigateToTarget() {
@@ -3816,7 +3821,7 @@ function renderCmdList(myCmds, userId) {
3816
3821
  );
3817
3822
  });
3818
3823
 
3819
- return html + "</div>";
3824
+ return html;
3820
3825
  }
3821
3826
 
3822
3827
  // ── 命令管理操作 ──
@@ -3896,6 +3901,13 @@ function wdToggleClientCmd(userId, idx) {
3896
3901
  } else {
3897
3902
  cmd.enabled = !cmd.enabled;
3898
3903
  }
3904
+ // 立即更新按钮为 loading 状态
3905
+ var btn = event.target;
3906
+ if (btn && btn.tagName === "BUTTON") {
3907
+ btn.textContent = "⏳";
3908
+ btn.style.pointerEvents = "none";
3909
+ btn.style.opacity = "0.5";
3910
+ }
3899
3911
  wdSaveClientCmds(userId, myCmds);
3900
3912
  }
3901
3913
 
@@ -3909,6 +3921,8 @@ async function wdSaveClientCmds(userId, commands) {
3909
3921
  fetchWatchdogData();
3910
3922
  } catch (e) {
3911
3923
  alert("保存失败: " + e.message);
3924
+ // 失败时立即刷新恢复按钮状态
3925
+ fetchWatchdogData();
3912
3926
  }
3913
3927
  }
3914
3928
 
@@ -11,10 +11,23 @@
11
11
 
12
12
  import { spawn, execSync } from "child_process";
13
13
  import { EventEmitter } from "events";
14
+ import { killEdgeProcesses } from "../lib/browser/cdp.js";
14
15
 
15
16
  const MAX_RESTART = 3;
16
17
  const IS_WIN = process.platform === "win32";
17
18
 
19
+ // 从命令行中提取 CDP 端口列表(解析 --base-port 和 --port-count)
20
+ function extractCdpPorts(cmdLine) {
21
+ const match = cmdLine.match(/--base-port\s+(\d+)/);
22
+ if (!match) return [];
23
+ const base = parseInt(match[1], 10);
24
+ const countMatch = cmdLine.match(/--port-count\s+(\d+)/);
25
+ const count = countMatch ? parseInt(countMatch[1], 10) : 1;
26
+ const ports = [];
27
+ for (let i = 0; i < count; i++) ports.push(base + i);
28
+ return ports;
29
+ }
30
+
18
31
  // 引号感知的命令拆分:"a b" "c d" → ["a b", "c d"]
19
32
  function splitCommand(cmdLine) {
20
33
  const parts = [];
@@ -112,9 +125,9 @@ export class ProcessManager extends EventEmitter {
112
125
  command = parts[0] || command;
113
126
  args = parts.slice(1);
114
127
  }
115
- // Windows .cmd 文件必须 shell:true,macOS/Linux 直接 spawn
128
+ // Windows .cmd 必须 shell:true;为免 DEP0190 警告,传完整命令行字符串
116
129
  child = IS_WIN
117
- ? spawn(command, args, {
130
+ ? spawn([command, ...args].join(" "), {
118
131
  stdio: ["ignore", "pipe", "pipe"],
119
132
  detached: false,
120
133
  shell: true,
@@ -210,6 +223,10 @@ export class ProcessManager extends EventEmitter {
210
223
 
211
224
  if (info.child) {
212
225
  try {
226
+ // 先从命令行提取 CDP 端口,用于关闭脱离进程树的浏览器
227
+ const cmdLine = info.cmdDef?.command || "";
228
+ const ports = extractCdpPorts(cmdLine);
229
+
213
230
  if (IS_WIN) {
214
231
  // Windows: shell:true 产生 cmd.exe 中间层,必须杀整个进程树
215
232
  execSync(`taskkill /PID ${info.child.pid} /T /F`, {
@@ -227,6 +244,11 @@ export class ProcessManager extends EventEmitter {
227
244
  } catch {}
228
245
  }, 2000);
229
246
  }
247
+
248
+ // 全平台:关闭脱离进程树的浏览器(open -a / start msedge 启动的)
249
+ for (const port of ports) {
250
+ killEdgeProcesses(null, port);
251
+ }
230
252
  } catch (e) {
231
253
  console.error(`[watchdog] 停止命令 ${cmdId} 失败: ${e.message}`);
232
254
  }