tt-help-cli-ycl 1.3.18 → 1.3.19

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.3.18",
3
+ "version": "1.3.19",
4
4
  "description": "TikTok user & video data scraper - extract ttSeller, verified, locationCreated from HTML source",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,68 @@
1
+ @ECHO OFF
2
+ SETLOCAL
3
+
4
+ SET "PACKAGENAME=tt-help-cli-ycl"
5
+ SET "TARGET_SERVER=http://117.71.53.99:17301"
6
+ SET "CONFIG_PATH=%USERPROFILE%\.tt-help.json"
7
+
8
+ ECHO ========================================
9
+ ECHO tt-help-cli-ycl one-click launcher (Windows CMD)
10
+ ECHO ========================================
11
+
12
+ REM ---------- 1. Check/install latest version ----------
13
+ FOR /F "delims=" %%V IN ('npm view %PACKAGENAME% version 2^>nul') DO SET "LATEST_VERSION=%%V"
14
+
15
+ IF NOT DEFINED LATEST_VERSION (
16
+ ECHO [ERROR] Cannot get latest version from npm
17
+ EXIT /B 1
18
+ )
19
+
20
+ FOR /F "tokens=2 delims=@" %%V IN ('npm list -g %PACKAGENAME% --depth=0 2^>nul ^| findstr /i "%PACKAGENAME%"') DO SET "INSTALLED_VERSION=%%V"
21
+
22
+ IF NOT DEFINED INSTALLED_VERSION (
23
+ ECHO [INFO] %PACKAGENAME% not installed, installing latest...
24
+ CALL npm install -g %PACKAGENAME%
25
+ IF %ERRORLEVEL% EQU 0 (
26
+ ECHO [OK] Installed: %LATEST_VERSION%
27
+ ) ELSE (
28
+ ECHO [ERROR] Install failed, run manually: npm install -g %PACKAGENAME%
29
+ EXIT /B 1
30
+ )
31
+ ) ELSE IF "%INSTALLED_VERSION%"=="%LATEST_VERSION%" (
32
+ ECHO [OK] %PACKAGENAME% is up to date: %LATEST_VERSION%
33
+ ) ELSE (
34
+ ECHO [INFO] Current: %INSTALLED_VERSION%, Latest: %LATEST_VERSION%
35
+ ECHO [INFO] Upgrading to latest...
36
+ CALL npm install -g %PACKAGENAME%
37
+ IF %ERRORLEVEL% EQU 0 (
38
+ ECHO [OK] Upgraded: %LATEST_VERSION%
39
+ ) ELSE (
40
+ ECHO [WARN] Upgrade failed, run manually: npm install -g %PACKAGENAME%
41
+ )
42
+ )
43
+
44
+ REM ---------- 2. Check/set server config ----------
45
+ SET "CURRENT_SERVER="
46
+ IF EXIST "%CONFIG_PATH%" (
47
+ FOR /F "delims=" %%S IN ('node -e "try{const c=JSON.parse(require('fs').readFileSync('%CONFIG_PATH%','utf-8'));console.log(c.server||'')}catch(e){}" 2^>nul') DO SET "CURRENT_SERVER=%%S"
48
+ )
49
+
50
+ IF "%CURRENT_SERVER%"=="%TARGET_SERVER%" (
51
+ ECHO [OK] Server config is correct: %TARGET_SERVER%
52
+ ) ELSE (
53
+ IF "%CURRENT_SERVER%"=="" (
54
+ ECHO [INFO] Current server: not set, target: %TARGET_SERVER%
55
+ ) ELSE (
56
+ ECHO [INFO] Current server: %CURRENT_SERVER%, target: %TARGET_SERVER%
57
+ )
58
+ ECHO [INFO] Setting server config...
59
+ node -e "const fs=require('fs'),path=require('path');const p=path.join(require('os').homedir(),'.tt-help.json');let c={};try{c=JSON.parse(fs.readFileSync(p,'utf-8'))}catch(e){}c.server='%TARGET_SERVER%';fs.writeFileSync(p,JSON.stringify(c,null,2),'utf-8');console.log(' Written to: '+p);"
60
+ ECHO [OK] Server config set
61
+ )
62
+
63
+ REM ---------- 3. Start tt-help explore ----------
64
+ ECHO.
65
+ ECHO ========================================
66
+ ECHO Starting tt-help explore
67
+ ECHO ========================================
68
+ tt-help explore --port 9223 --profile p9223
@@ -138,44 +138,69 @@ export function createStore(filePath) {
138
138
  }
139
139
  }
140
140
 
141
+ // 异步 save:不阻塞事件循环,排队保证顺序
142
+ // 多次 save 调用之间如果已有 save 在进行,只标记需要再次保存
143
+ let saveInFlight = false;
144
+ let pendingSave = false;
145
+
141
146
  function save() {
142
147
  if (!filePath) return;
148
+ if (saveInFlight) {
149
+ pendingSave = true;
150
+ return;
151
+ }
152
+ doSave();
153
+ }
154
+
155
+ async function doSave() {
156
+ saveInFlight = true;
143
157
  const resolved = path.resolve(filePath);
144
158
 
145
- // 将 done 用户归档到独立文件
146
- if (doneArchivePath && data.length > 1000) {
147
- const active = [];
148
- const toArchive = [];
149
- for (const u of data) {
150
- if (u.status === 'done') {
151
- toArchive.push(u);
152
- } else {
153
- active.push(u);
159
+ try {
160
+ // done 用户归档到独立文件
161
+ if (doneArchivePath && data.length > 1000) {
162
+ const active = [];
163
+ const toArchive = [];
164
+ for (const u of data) {
165
+ if (u.status === 'done') {
166
+ toArchive.push(u);
167
+ } else {
168
+ active.push(u);
169
+ }
154
170
  }
155
- }
156
- if (toArchive.length > 0) {
157
- doneArchive = doneArchive.concat(toArchive);
158
- data = active;
159
- rebuildIndex();
160
- // 重建 done 归档索引
161
- doneUidIndex = new Map();
162
- for (let i = 0; i < doneArchive.length; i++) {
163
- doneUidIndex.set(doneArchive[i].uniqueId, i);
171
+ if (toArchive.length > 0) {
172
+ doneArchive = doneArchive.concat(toArchive);
173
+ data.length = 0;
174
+ data.push(...active);
175
+ rebuildIndex();
176
+ doneUidIndex = new Map();
177
+ for (let i = 0; i < doneArchive.length; i++) {
178
+ doneUidIndex.set(doneArchive[i].uniqueId, i);
179
+ }
164
180
  }
165
181
  }
166
- }
167
182
 
168
- const json = JSON.stringify(data);
169
- const tmpPath = resolved + '.tmp';
170
- fs.writeFileSync(tmpPath, json, 'utf-8');
171
- fs.renameSync(tmpPath, resolved);
172
-
173
- // 写 done 归档
174
- if (doneArchivePath && doneArchive.length > 0) {
175
- const doneJson = JSON.stringify(doneArchive);
176
- const doneTmp = doneArchivePath + '.tmp';
177
- fs.writeFileSync(doneTmp, doneJson, 'utf-8');
178
- fs.renameSync(doneTmp, doneArchivePath);
183
+ const json = JSON.stringify(data);
184
+ const tmpPath = resolved + '.tmp';
185
+ await fs.promises.writeFile(tmpPath, json, 'utf-8');
186
+ await fs.promises.rename(tmpPath, resolved);
187
+
188
+ // 写 done 归档
189
+ if (doneArchivePath && doneArchive.length > 0) {
190
+ const doneJson = JSON.stringify(doneArchive);
191
+ const doneTmp = doneArchivePath + '.tmp';
192
+ await fs.promises.writeFile(doneTmp, doneJson, 'utf-8');
193
+ await fs.promises.rename(doneTmp, doneArchivePath);
194
+ }
195
+ } catch (e) {
196
+ console.error(`[DataStore] save error: ${e.message}`);
197
+ } finally {
198
+ saveInFlight = false;
199
+ // 如果有排队的 save,继续执行
200
+ if (pendingSave) {
201
+ pendingSave = false;
202
+ doSave();
203
+ }
179
204
  }
180
205
  }
181
206