tt-help-cli-ycl 1.3.57 → 1.3.58
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/src/lib/api-interceptor.js +6 -2
- package/src/scraper/explore-core.js +10 -0
- package/src/watch/data-store.js +30 -8
- package/src/watch/public/app.js +1266 -0
- package/src/watch/public/index.html +4 -2182
- package/src/watch/public/style.css +1070 -0
- package/src/watch/server.js +19 -0
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@ async function processAPIResponse(
|
|
|
18
18
|
for (const item of firstPageItems) {
|
|
19
19
|
if (items.length >= maxVideos) break;
|
|
20
20
|
const href = `https://www.tiktok.com/@${username}/video/${item.id}`;
|
|
21
|
-
items.push({ id: item.id, href });
|
|
21
|
+
items.push({ id: item.id, href, createTime: item.createTime || null });
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
let cursor = data.cursor;
|
|
@@ -59,7 +59,11 @@ async function processAPIResponse(
|
|
|
59
59
|
for (const item of pageData.itemList) {
|
|
60
60
|
if (items.length >= maxVideos) break;
|
|
61
61
|
const href = `https://www.tiktok.com/@${username}/video/${item.id}`;
|
|
62
|
-
items.push({
|
|
62
|
+
items.push({
|
|
63
|
+
id: item.id,
|
|
64
|
+
href,
|
|
65
|
+
createTime: item.createTime || null,
|
|
66
|
+
});
|
|
63
67
|
}
|
|
64
68
|
}
|
|
65
69
|
|
|
@@ -37,6 +37,7 @@ async function processExplore(page, username, options, log) {
|
|
|
37
37
|
hasFollowData: false,
|
|
38
38
|
keepFollow: false,
|
|
39
39
|
locationCreated: null,
|
|
40
|
+
latestVideoTime: null,
|
|
40
41
|
noVideo: false,
|
|
41
42
|
restricted: false,
|
|
42
43
|
error: null,
|
|
@@ -67,6 +68,15 @@ async function processExplore(page, username, options, log) {
|
|
|
67
68
|
const videoArray = videoList ? [...videoList.values()] : [];
|
|
68
69
|
result.collectedVideos = videoArray.length;
|
|
69
70
|
|
|
71
|
+
// 从视频列表中找最近的作品发布时间
|
|
72
|
+
const latestCreateTime = videoArray
|
|
73
|
+
.filter((v) => v.createTime)
|
|
74
|
+
.reduce((max, v) => (v.createTime > max ? v.createTime : max), 0);
|
|
75
|
+
if (latestCreateTime > 0) {
|
|
76
|
+
result.latestVideoTime = latestCreateTime;
|
|
77
|
+
if (result.userInfo) result.userInfo.latestVideoTime = latestCreateTime;
|
|
78
|
+
}
|
|
79
|
+
|
|
70
80
|
if (videoArray.length <= 0) {
|
|
71
81
|
// 视频为空:可能是页面受限或用户真的没有视频
|
|
72
82
|
result.processed = true;
|
package/src/watch/data-store.js
CHANGED
|
@@ -129,6 +129,9 @@ function initUserDb(filePath) {
|
|
|
129
129
|
if (!existingJobColumns.has("status_code")) {
|
|
130
130
|
db.exec(`ALTER TABLE jobs ADD COLUMN status_code INTEGER`);
|
|
131
131
|
}
|
|
132
|
+
if (!existingJobColumns.has("latest_video_time")) {
|
|
133
|
+
db.exec(`ALTER TABLE jobs ADD COLUMN latest_video_time INTEGER`);
|
|
134
|
+
}
|
|
132
135
|
db.exec(`
|
|
133
136
|
CREATE TABLE IF NOT EXISTS raw_jobs (
|
|
134
137
|
unique_id TEXT PRIMARY KEY,
|
|
@@ -159,7 +162,8 @@ function initUserDb(filePath) {
|
|
|
159
162
|
region TEXT,
|
|
160
163
|
signature TEXT,
|
|
161
164
|
sec_uid TEXT,
|
|
162
|
-
status_code INTEGER
|
|
165
|
+
status_code INTEGER,
|
|
166
|
+
latest_video_time INTEGER
|
|
163
167
|
)
|
|
164
168
|
`);
|
|
165
169
|
|
|
@@ -173,6 +177,9 @@ function initUserDb(filePath) {
|
|
|
173
177
|
if (!existingRawJobColumns.has("status_code")) {
|
|
174
178
|
db.exec(`ALTER TABLE raw_jobs ADD COLUMN status_code INTEGER`);
|
|
175
179
|
}
|
|
180
|
+
if (!existingRawJobColumns.has("latest_video_time")) {
|
|
181
|
+
db.exec(`ALTER TABLE raw_jobs ADD COLUMN latest_video_time INTEGER`);
|
|
182
|
+
}
|
|
176
183
|
db.exec(`
|
|
177
184
|
CREATE TABLE IF NOT EXISTS videos (
|
|
178
185
|
id TEXT PRIMARY KEY,
|
|
@@ -187,7 +194,8 @@ function initUserDb(filePath) {
|
|
|
187
194
|
comment_count INTEGER,
|
|
188
195
|
share_count INTEGER,
|
|
189
196
|
collect_count INTEGER,
|
|
190
|
-
stats_updated_at INTEGER
|
|
197
|
+
stats_updated_at INTEGER,
|
|
198
|
+
create_time INTEGER
|
|
191
199
|
)
|
|
192
200
|
`);
|
|
193
201
|
db.exec(`
|
|
@@ -280,6 +288,11 @@ function initUserDb(filePath) {
|
|
|
280
288
|
}
|
|
281
289
|
}
|
|
282
290
|
|
|
291
|
+
// 迁移:videos 表添加 create_time 列
|
|
292
|
+
if (!existingVideoColumns.has("create_time")) {
|
|
293
|
+
db.exec(`ALTER TABLE videos ADD COLUMN create_time INTEGER`);
|
|
294
|
+
}
|
|
295
|
+
|
|
283
296
|
const count = db.prepare("SELECT COUNT(*) as c FROM users").get().c;
|
|
284
297
|
console.log(`[data-store] SQLite users 表初始化完成: ${count} 条`);
|
|
285
298
|
}
|
|
@@ -311,9 +324,10 @@ export function importLegacyJsonToDb({
|
|
|
311
324
|
location_created,
|
|
312
325
|
tt_seller,
|
|
313
326
|
registered_at,
|
|
314
|
-
user_update_count
|
|
327
|
+
user_update_count,
|
|
328
|
+
create_time
|
|
315
329
|
)
|
|
316
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
330
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
317
331
|
`);
|
|
318
332
|
|
|
319
333
|
const importUsersTxn = db.transaction((items) => {
|
|
@@ -336,6 +350,7 @@ export function importLegacyJsonToDb({
|
|
|
336
350
|
item.ttSeller ? 1 : 0,
|
|
337
351
|
item.registeredAt || item.registered_at || Date.now(),
|
|
338
352
|
item.userUpdateCount || item.user_update_count || 0,
|
|
353
|
+
item.createTime || item.create_time || null,
|
|
339
354
|
);
|
|
340
355
|
}
|
|
341
356
|
});
|
|
@@ -857,7 +872,8 @@ function moveJobsToRawByCountry(scope, country) {
|
|
|
857
872
|
updated_at,
|
|
858
873
|
region,
|
|
859
874
|
signature,
|
|
860
|
-
sec_uid
|
|
875
|
+
sec_uid,
|
|
876
|
+
latest_video_time
|
|
861
877
|
)
|
|
862
878
|
SELECT
|
|
863
879
|
unique_id,
|
|
@@ -887,7 +903,8 @@ function moveJobsToRawByCountry(scope, country) {
|
|
|
887
903
|
updated_at,
|
|
888
904
|
region,
|
|
889
905
|
signature,
|
|
890
|
-
sec_uid
|
|
906
|
+
sec_uid,
|
|
907
|
+
latest_video_time
|
|
891
908
|
FROM jobs
|
|
892
909
|
WHERE ${whereSql}
|
|
893
910
|
`,
|
|
@@ -1293,6 +1310,7 @@ function getTargetUsersFromDb(targetLocations = []) {
|
|
|
1293
1310
|
tt_seller,
|
|
1294
1311
|
verified,
|
|
1295
1312
|
location_created,
|
|
1313
|
+
latest_video_time,
|
|
1296
1314
|
status,
|
|
1297
1315
|
sources
|
|
1298
1316
|
FROM jobs
|
|
@@ -1359,6 +1377,7 @@ const writableJobColumns = new Set([
|
|
|
1359
1377
|
"signature",
|
|
1360
1378
|
"sec_uid",
|
|
1361
1379
|
"status_code",
|
|
1380
|
+
"latest_video_time",
|
|
1362
1381
|
]);
|
|
1363
1382
|
|
|
1364
1383
|
function normalizeJobValue(column, value) {
|
|
@@ -3119,9 +3138,10 @@ export function createStore(filePath) {
|
|
|
3119
3138
|
location_created,
|
|
3120
3139
|
tt_seller,
|
|
3121
3140
|
registered_at,
|
|
3122
|
-
user_update_count
|
|
3141
|
+
user_update_count,
|
|
3142
|
+
create_time
|
|
3123
3143
|
)
|
|
3124
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
3144
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
3125
3145
|
`);
|
|
3126
3146
|
let registered = 0;
|
|
3127
3147
|
let skipped = 0;
|
|
@@ -3136,6 +3156,7 @@ export function createStore(filePath) {
|
|
|
3136
3156
|
ttSeller ? 1 : 0,
|
|
3137
3157
|
now,
|
|
3138
3158
|
0,
|
|
3159
|
+
item.createTime || null,
|
|
3139
3160
|
);
|
|
3140
3161
|
if (result.changes > 0) registered++;
|
|
3141
3162
|
else skipped++;
|
|
@@ -3161,6 +3182,7 @@ export function createStore(filePath) {
|
|
|
3161
3182
|
locationCreated: locationCreated || null,
|
|
3162
3183
|
ttSeller: ttSeller || false,
|
|
3163
3184
|
registeredAt: Date.now(),
|
|
3185
|
+
createTime: item.createTime || null,
|
|
3164
3186
|
});
|
|
3165
3187
|
existingIds.add(item.id);
|
|
3166
3188
|
registered++;
|