tt-help-cli-ycl 1.4.144 → 1.4.145
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 +1 -1
- package/scripts/test-daemon-failover.mjs +61 -4
- package/src/clash/checker.js +41 -0
- package/src/clash/daemon.js +26 -0
- package/src/cli/tag.js +104 -329
- package/src/lib/constants.js +6 -5
- package/src/watch/data-store.js +88 -0
- package/src/watch/public/app.js +232 -0
- package/src/watch/public/index.html +53 -0
- package/src/watch/public/style.css +202 -0
- package/src/watch/server.js +60 -0
- package/src/watchdog/process-manager.js +11 -6
package/src/watch/server.js
CHANGED
|
@@ -114,6 +114,22 @@ const STAT_GROUPS = {
|
|
|
114
114
|
FROM jobs_done
|
|
115
115
|
)`,
|
|
116
116
|
},
|
|
117
|
+
{
|
|
118
|
+
// 精确商家计数:目标商家 + 7 天 EC 视频播放>1000 + 有商品 + 评论0 + 销量>10
|
|
119
|
+
key: "preciseMerchants",
|
|
120
|
+
mode: "one",
|
|
121
|
+
params: () => getTargetLocations(),
|
|
122
|
+
sql: () => `SELECT COUNT(*) AS n FROM jobs
|
|
123
|
+
WHERE tt_seller = 1 AND verified = 0 AND ${targetInSql()}
|
|
124
|
+
AND top_video_seo_url IS NOT NULL AND top_video_seo_url != ''
|
|
125
|
+
AND product_review_count = 0
|
|
126
|
+
AND product_sold_count > 10
|
|
127
|
+
AND recent_ec_videos IS NOT NULL AND recent_ec_videos != ''
|
|
128
|
+
AND EXISTS (
|
|
129
|
+
SELECT 1 FROM json_each(recent_ec_videos)
|
|
130
|
+
WHERE CAST(json_extract(value, '$.playCount') AS INTEGER) > 1000
|
|
131
|
+
)`,
|
|
132
|
+
},
|
|
117
133
|
],
|
|
118
134
|
combine(results) {
|
|
119
135
|
const tq = results.tqAgg || {};
|
|
@@ -129,6 +145,7 @@ const STAT_GROUPS = {
|
|
|
129
145
|
restrictedUsers: jb.restricted || 0,
|
|
130
146
|
errorUsers: jb.error || 0,
|
|
131
147
|
targetUsers: jb.targetUsers || 0,
|
|
148
|
+
preciseMerchants: results.preciseMerchants?.n || 0,
|
|
132
149
|
sourceStats: {
|
|
133
150
|
seed: tq.seed || 0,
|
|
134
151
|
video: tq.video || 0,
|
|
@@ -256,6 +273,7 @@ const EMPTY_GROUP = {
|
|
|
256
273
|
restrictedUsers: 0,
|
|
257
274
|
errorUsers: 0,
|
|
258
275
|
targetUsers: 0,
|
|
276
|
+
preciseMerchants: 0,
|
|
259
277
|
sourceStats: {
|
|
260
278
|
seed: 0,
|
|
261
279
|
video: 0,
|
|
@@ -1551,6 +1569,48 @@ export function startWatchServer(
|
|
|
1551
1569
|
return;
|
|
1552
1570
|
}
|
|
1553
1571
|
|
|
1572
|
+
// GET /api/precise-merchants — 精确商家列表(支持分页+搜索)
|
|
1573
|
+
if (req.method === "GET" && routePath === "/api/precise-merchants") {
|
|
1574
|
+
const result = store.getPreciseMerchants(getTargetLocations(), {
|
|
1575
|
+
search: params.search || undefined,
|
|
1576
|
+
limit: params.limit ? parseInt(params.limit, 10) : undefined,
|
|
1577
|
+
offset: params.offset ? parseInt(params.offset, 10) : undefined,
|
|
1578
|
+
});
|
|
1579
|
+
if (result && result.users) {
|
|
1580
|
+
result.users = result.users.map((u) => ({
|
|
1581
|
+
uniqueId: u.uniqueId,
|
|
1582
|
+
nickname: u.nickname || "",
|
|
1583
|
+
locationCreated: u.locationCreated || null,
|
|
1584
|
+
followerCount: u.followerCount || 0,
|
|
1585
|
+
videoCount: u.videoCount || 0,
|
|
1586
|
+
latestVideoTime: u.latestVideoTime || null,
|
|
1587
|
+
topVideoPlayCount: u.topVideoPlayCount || null,
|
|
1588
|
+
topVideoHref: u.topVideoHref || null,
|
|
1589
|
+
topVideoIsAd: u.topVideoIsAd ?? null,
|
|
1590
|
+
topVideoProductId: u.topVideoProductId || null,
|
|
1591
|
+
topVideoProductTitle: u.topVideoProductTitle || null,
|
|
1592
|
+
topVideoSeoUrl: u.topVideoSeoUrl || null,
|
|
1593
|
+
productRating: u.productRating ?? null,
|
|
1594
|
+
productReviewCount: u.productReviewCount ?? null,
|
|
1595
|
+
productSoldCount: u.productSoldCount ?? null,
|
|
1596
|
+
productName: u.productName || null,
|
|
1597
|
+
ecOver1k: u.ecOver1k || 0,
|
|
1598
|
+
maxEcPlay: u.maxEcPlay || null,
|
|
1599
|
+
recentEcVideos: (() => {
|
|
1600
|
+
try {
|
|
1601
|
+
return Array.isArray(u.recentEcVideos)
|
|
1602
|
+
? u.recentEcVideos
|
|
1603
|
+
: JSON.parse(u.recentEcVideos || "[]");
|
|
1604
|
+
} catch {
|
|
1605
|
+
return [];
|
|
1606
|
+
}
|
|
1607
|
+
})(),
|
|
1608
|
+
}));
|
|
1609
|
+
}
|
|
1610
|
+
sendJSON(res, 200, result);
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1554
1614
|
if (
|
|
1555
1615
|
req.method === "GET" &&
|
|
1556
1616
|
routePath === "/api/target-users-by-country"
|
|
@@ -22,8 +22,11 @@ import { pushSelfLog } from "./self-log-buffer.js";
|
|
|
22
22
|
const MAX_RESTART = 3;
|
|
23
23
|
const MAX_LOG_LINES = 500; // 每个进程最多保留的日志行数
|
|
24
24
|
const IS_WIN = process.platform === "win32";
|
|
25
|
-
const SPAWN_STAGGER_MS = 30000; // 批量启动时每个进程间隔 30 秒,避免抢网络
|
|
26
|
-
|
|
25
|
+
const SPAWN_STAGGER_MS = 30000; // syncCommands 批量启动时每个进程间隔 30 秒,避免抢网络
|
|
26
|
+
// 代理切换后强制重启(restartAll)专用错峰间隔:切换出口后所有命令集中重建连接,
|
|
27
|
+
// 间隔给长一点,避免瞬时抢网络/触发风控(2026-08-29 按需加长)
|
|
28
|
+
const RESTART_STOP_STAGGER_MS = 20000; // 停止错峰 20s(杀 Edge/进程树瞬时占资源,错峰释放)
|
|
29
|
+
const RESTART_SPAWN_STAGGER_MS = 60000; // 启动错峰 60s
|
|
27
30
|
const STALE_LOG_TIMEOUT_MS = 15 * 60 * 1000; // 15 分钟无日志输出视为假死
|
|
28
31
|
|
|
29
32
|
// === 控制台日志格式化(仅显示层增强,不影响任何功能链路) ===
|
|
@@ -739,9 +742,10 @@ export class ProcessManager extends EventEmitter {
|
|
|
739
742
|
console.error(
|
|
740
743
|
`[watchdog] ${reason},强制重启全部命令 (${toRestart.length}个)...`,
|
|
741
744
|
);
|
|
742
|
-
// 错峰停止:第一个立即停,之后每个间隔
|
|
745
|
+
// 错峰停止:第一个立即停,之后每个间隔 RESTART_STOP_STAGGER_MS(平滑释放资源,避免同时杀 N 个浏览器)
|
|
743
746
|
for (let i = 0; i < toRestart.length; i++) {
|
|
744
|
-
if (i > 0)
|
|
747
|
+
if (i > 0)
|
|
748
|
+
await new Promise((r) => setTimeout(r, RESTART_STOP_STAGGER_MS));
|
|
745
749
|
if (this.shutdown) {
|
|
746
750
|
console.error("[watchdog] 看门狗已停止,中止停止命令");
|
|
747
751
|
break;
|
|
@@ -751,9 +755,10 @@ export class ProcessManager extends EventEmitter {
|
|
|
751
755
|
`[watchdog] 命令 ${toRestart[i].id} 已停止 (${i + 1}/${toRestart.length})`,
|
|
752
756
|
);
|
|
753
757
|
}
|
|
754
|
-
// 错峰逐个重启:第一个立即起,之后每个间隔
|
|
758
|
+
// 错峰逐个重启:第一个立即起,之后每个间隔 RESTART_SPAWN_STAGGER_MS
|
|
755
759
|
for (let i = 0; i < toRestart.length; i++) {
|
|
756
|
-
if (i > 0)
|
|
760
|
+
if (i > 0)
|
|
761
|
+
await new Promise((r) => setTimeout(r, RESTART_SPAWN_STAGGER_MS));
|
|
757
762
|
if (this.shutdown) {
|
|
758
763
|
console.error("[watchdog] 看门狗已停止,中止重启命令");
|
|
759
764
|
break;
|