|
|
@@ -1,5 +1,5 @@
|
|
|
/*! tiktok-auto v1.0.0
|
|
|
- * built 2026-10-21T15:03:41.961Z
|
|
|
+ * built 2026-10-22T06:54:25.473Z
|
|
|
* modules: logger, bridge, config, wait, layout, ui, popups, tiktok, player, comment, flow, parse, uidset, filters, profile, idsource, resolve, idflow, main
|
|
|
* 由 tools/build.js 自动生成 —— 请不要直接编辑本文件,改 src/ 后重新构建。
|
|
|
*/
|
|
|
@@ -3260,11 +3260,30 @@ TikTokAuto.flow = (function () {
|
|
|
|
|
|
function launchApp(config) {
|
|
|
var step = 'launch';
|
|
|
- logger().step(step, '启动 ' + config.target.packageName);
|
|
|
- app.launchPackage(config.target.packageName);
|
|
|
+ var pkg = config.target.packageName;
|
|
|
+
|
|
|
+ /* ★ 已经在前台就**绝对别动它**。
|
|
|
+ *
|
|
|
+ * `app.launchPackage()` 不是"切到前台",而是"重新打开这个 app" ——
|
|
|
+ * 即使 app 已经在前台,它也会再发一次 startActivity,把叠在主界面上的
|
|
|
+ * 页面(视频播放页、评论面板、用户列表)清掉,退回首页。
|
|
|
+ *
|
|
|
+ * 对「当前屏幕」类取材这是致命的:用户手动把 TikTok 停在评论区,
|
|
|
+ * 那正是这个取材源的全部前提,而引擎一启动就把它退成了 feed,
|
|
|
+ * 然后再报"取材设置为当前屏幕,但当前不在播放页"。
|
|
|
+ * 实测(2026-10-22):日志里 `launch 就绪(56ms)` 看着毫秒级完成、
|
|
|
+ * 什么都没干,实际上页面已经被重置了 —— 时间是 56ms,副作用却不可逆。
|
|
|
+ */
|
|
|
+ if (TikTokAuto.layout.foregroundPackage() === pkg) {
|
|
|
+ logger().info(step, '已在前台,保持当前页面不动');
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ logger().step(step, '启动 ' + pkg);
|
|
|
+ app.launchPackage(pkg);
|
|
|
|
|
|
var ready = TikTokAuto.wait.waitFor(step, function () {
|
|
|
- return TikTokAuto.layout.foregroundPackage() === config.target.packageName ? true : null;
|
|
|
+ return TikTokAuto.layout.foregroundPackage() === pkg ? true : null;
|
|
|
}, config.timeouts.appLaunchMs, config.probe.pollTickMs);
|
|
|
|
|
|
return ready === true;
|
|
|
@@ -5048,6 +5067,8 @@ TikTokAuto.profile = (function () {
|
|
|
switchListTab: switchListTab,
|
|
|
listRows: listRows,
|
|
|
isListPage: isListPage,
|
|
|
+ /** 给外部用的"等主页就绪":等 @username + 三组数字,见 waitProfile 的注释 */
|
|
|
+ waitProfilePublic: function () { return waitProfile('waitProfile'); },
|
|
|
scrollList: scrollList,
|
|
|
openRow: openRow,
|
|
|
backToList: backToList,
|
|
|
@@ -5324,9 +5345,16 @@ TikTokAuto.idsource = (function () {
|
|
|
ctx.seen.add(marker);
|
|
|
|
|
|
TikTokAuto.ui.tapPoint(rows[i].x, rows[i].y);
|
|
|
- TikTokAuto.profile.settle(3000);
|
|
|
- if (TikTokAuto.profile.where() !== 'profile') {
|
|
|
- log.warn('idsource', '点评论者头像没有进入用户主页');
|
|
|
+ /* ★ 用 waitProfile(等 @username + 三组数字),而不是 settle + where()。
|
|
|
+ *
|
|
|
+ * 早先这里是"等页面安静 3 秒,再看 where() 是不是 profile":
|
|
|
+ * · settle 会提前返回(骨架先出、内容后加载,签名看起来没变);
|
|
|
+ * · 而 where() 要求 `@username` 已经渲染出来。
|
|
|
+ * 两头一凑,就成了"人明明已经进主页了,却被判成没进去"——
|
|
|
+ * 实测日志里连续两条"点评论者头像没有进入用户主页",然后一条都没取到。
|
|
|
+ */
|
|
|
+ if (!TikTokAuto.profile.waitProfilePublic()) {
|
|
|
+ log.warn('idsource', '点评论者头像没有进入用户主页(等了 10 秒)');
|
|
|
continue;
|
|
|
}
|
|
|
var profile = TikTokAuto.profile.readProfile();
|
|
|
@@ -5398,7 +5426,16 @@ TikTokAuto.idsource = (function () {
|
|
|
}
|
|
|
|
|
|
if (source.kind === 'screen') {
|
|
|
- /* 当前屏幕:不做任何导航,直接把眼前这一屏当列表读 */
|
|
|
+ /* 当前屏幕:不做任何导航,直接把眼前这一屏当列表读。
|
|
|
+ *
|
|
|
+ * 但要先确认眼前确实是"一个用户列表" —— 否则 walkList 会一屏一屏地读,
|
|
|
+ * 最后报"处理 0 行",用户完全不知道是页面不对。 */
|
|
|
+ var state = TikTokAuto.profile.where();
|
|
|
+ if (!TikTokAuto.profile.isListPage(state)) {
|
|
|
+ log.warn('idsource', '当前屏幕取材:需要先把页面停在「用户列表」(粉丝/关注/搜索用户)上,' +
|
|
|
+ '引擎不会替你跳转。现在停在「' + state + '」');
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
return walkList(ctx);
|
|
|
}
|
|
|
|
|
|
@@ -5554,7 +5591,11 @@ TikTokAuto.idsource = (function () {
|
|
|
log.info('idsource', '已在播放页,直接用当前屏幕的视频');
|
|
|
return true;
|
|
|
}
|
|
|
- log.warn('idsource', '取材设置为「当前屏幕」,但当前不在播放页(' + state + ')');
|
|
|
+ /* 这里的提示必须是**可操作**的:用户能做的只有三件事 —— 自己先把页面停好、
|
|
|
+ * 改用关键词模式、或者换一个取材源。不能只说"不在播放页"。 */
|
|
|
+ log.warn('idsource', '「当前屏幕」需要用你手上已经打开的那个视频,引擎不会替你跳转。\n' +
|
|
|
+ ' 请先在 TikTok 里打开视频(或直接打开它的评论区),再点「开始运行」。\n' +
|
|
|
+ ' 当前页面是「' + state + '」。');
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -6412,11 +6453,19 @@ TikTokAuto.idflow = (function () {
|
|
|
summary.errors.push('启动应用失败');
|
|
|
return summary;
|
|
|
}
|
|
|
- progress('进入信息流', 0);
|
|
|
- if (!TikTokAuto.profile.ensureFeed(config)) {
|
|
|
- summary.errors.push('未能进入信息流首页');
|
|
|
- return summary;
|
|
|
- }
|
|
|
+ /* ★ 这里**刻意不做 ensureFeed**。
|
|
|
+ *
|
|
|
+ * 早先这里无条件把页面退回信息流首页,于是「当前屏幕」类的取材必然失败:
|
|
|
+ * 用户手动把 TikTok 停在视频评论区(那正是这个取材源的全部前提),
|
|
|
+ * 引擎一上来就连按几次返回退到首页,然后再报"取材设置为当前屏幕,
|
|
|
+ * 但当前不在播放页(feed)"。用户看到的是"我明明停在评论区,它说我不在"。
|
|
|
+ *
|
|
|
+ * 各个取材源自己知道自己需要什么前置状态,让它们自己保证:
|
|
|
+ * · 指定账号 / 搜索 → 走 prepareSearch,内部会 ensureFeed;
|
|
|
+ * · 视频/当前屏幕 → **不动页面**,就用用户准备好的那一屏;
|
|
|
+ * · 文本文件 → 根本不需要 UI。
|
|
|
+ */
|
|
|
+ progress('准备取材', 0);
|
|
|
|
|
|
if (settings.sources.length === 0) {
|
|
|
summary.errors.push('没有配置任何取材(界面里至少需要一条)');
|