tt-help-cli-ycl 1.4.54 → 1.4.56

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.54",
3
+ "version": "1.4.56",
4
4
  "description": "TikTok user & video data scraper - extract ttSeller, verified, locationCreated from HTML source",
5
5
  "type": "module",
6
6
  "bin": {
package/src/lib/args.js CHANGED
@@ -407,7 +407,8 @@ function parseWebserverArgs(args) {
407
407
  let webserverPort = 3000;
408
408
  let webserverPoolSize = 0;
409
409
  let webserverProxy = null;
410
- let webserverNotify = null;
410
+ // 默认汇报到 ~/.tt-help.json 中配置的 server 地址
411
+ let webserverNotify = defaultServer;
411
412
 
412
413
  for (let i = 0; i < args.length; i++) {
413
414
  const arg = args[i];
@@ -419,9 +420,9 @@ function parseWebserverArgs(args) {
419
420
  webserverProxy = args[++i] || null;
420
421
  } else if (arg === "--notify") {
421
422
  const next = args[i + 1];
422
- // 没写地址或下一个是别的参数 → 使用默认 watch 服务器
423
+ // 没写地址或下一个是别的参数 → 使用配置中的 server 地址
423
424
  if (!next || next.startsWith("--")) {
424
- webserverNotify = "http://117.71.53.99:17301";
425
+ webserverNotify = defaultServer;
425
426
  } else {
426
427
  webserverNotify = args[++i];
427
428
  }
@@ -2,6 +2,7 @@ import http from "http";
2
2
  import os from "os";
3
3
  import { TikTokScraper } from "../lib/tiktok-scraper.mjs";
4
4
  import { getProductInfo } from "../lib/shop-scraper.mjs";
5
+ import { userId as configUserId } from "../lib/constants.js";
5
6
 
6
7
  // ---- 工具函数 ----
7
8
 
@@ -238,21 +239,25 @@ async function handleTiktokProduct(req, res) {
238
239
  // 防止重复弹浏览器
239
240
  let captchaRecoveryRunning = false;
240
241
 
241
- async function scheduleCaptchaRecovery(url, proxy) {
242
- if (captchaRecoveryRunning) {
243
- console.error("[webserver] Captcha recovery already in progress, skipping");
242
+ // 通知 Watch Server:带重试,不受 captchaRecoveryRunning 锁限制
243
+ // captchaNotifyUrl 默认来自 ~/.tt-help.json 的 server 配置
244
+ async function notifyCaptchaToWatch(url, maxRetries = 3) {
245
+ if (!SCRAPER_CONFIG.captchaNotifyUrl) {
246
+ console.error(
247
+ "[webserver] Captcha detected but notify URL is empty, check --notify or ~/.tt-help.json server config",
248
+ );
244
249
  return;
245
250
  }
246
- captchaRecoveryRunning = true;
247
251
 
248
- // 通知 Watch Server:这台机器出现验证码需要人工处理
249
- if (SCRAPER_CONFIG.captchaNotifyUrl) {
252
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
250
253
  try {
251
254
  await fetch(`${SCRAPER_CONFIG.captchaNotifyUrl}/api/error-report`, {
252
255
  method: "POST",
253
256
  headers: { "Content-Type": "application/json" },
254
257
  body: JSON.stringify({
255
- userId: `webserver-${process.env.HOSTNAME || os.hostname() || "unknown"}`,
258
+ userId:
259
+ configUserId ||
260
+ `webserver-${process.env.HOSTNAME || os.hostname() || "unknown"}`,
256
261
  errorType: "captcha",
257
262
  errorMessage:
258
263
  "TikTok Shop captcha detected, browser opened - manual intervention required",
@@ -261,10 +266,35 @@ async function scheduleCaptchaRecovery(url, proxy) {
261
266
  }),
262
267
  });
263
268
  console.error("[webserver] Captcha alert sent to watch server");
269
+ return;
264
270
  } catch (e) {
265
- console.error("[webserver] Failed to notify watch server:", e.message);
271
+ if (attempt < maxRetries) {
272
+ const delay = attempt * 2000;
273
+ console.error(
274
+ `[webserver] Failed to notify watch server (attempt ${attempt}/${maxRetries}): ${e.message}, retrying in ${delay}ms...`,
275
+ );
276
+ await new Promise((r) => setTimeout(r, delay));
277
+ } else {
278
+ console.error(
279
+ `[webserver] Failed to notify watch server after ${maxRetries} attempts: ${e.message}`,
280
+ );
281
+ }
266
282
  }
267
283
  }
284
+ }
285
+
286
+ async function scheduleCaptchaRecovery(url, proxy) {
287
+ // 通知 Watch Server — 独立于浏览器恢复,每次验证码都尝试上报(带重试)
288
+ await notifyCaptchaToWatch(url);
289
+
290
+ // 防止重复弹浏览器
291
+ if (captchaRecoveryRunning) {
292
+ console.error(
293
+ "[webserver] Captcha recovery already in progress, skipping browser",
294
+ );
295
+ return;
296
+ }
297
+ captchaRecoveryRunning = true;
268
298
 
269
299
  try {
270
300
  const { getProductInfo } = await import("../lib/shop-scraper.mjs");