yuyin333

yuyin333 が dumengxingzhou/tiktok-scripts に main をプッシュしました

  • d10b7f1d6a 文档对齐:心跳与三段停止;补一条真机调试坑 上一轮代码改完了,但有几处面向人的说明还停在改造前,会误导后面接手的人: - 根 README:通道图补 engine-beat / run-log,文件数按实际列; 「已知能力边界」整段过时(说 ID提取/私信/养号没引擎,三个引擎早做完了), 改成当前真实边界:四任务都有引擎,唯一做不了的是评论发布(发送键是自绘控件,树下没节点) - tiktok-app/README:文件表补 engine-beat / run-log;「两步停止」改三段 (正在通知引擎 → 正在收尾 → 终态),超时 8s 改 ack 3s + 收尾 10s; 补一句心跳 ack 的定位(防御性保险,正常路径主流程 750ms 就自己发现停止了,更快); 验收清单同步,并把「未接入脚本被拦下」标注为已无天然样本 - bridge.js 头注释:四个约定文件 → 五个,说明 run-state 与 engine-beat 为什么要分开 - PROTOCOL.md §7.1:写清心跳 ack 是保险不是主路,以及"别在真实流程里抢观察窗口"(抢不到) - AI_CONTEXT §6.B 新增 B0:运行中 uiautomator dump 会静默返回上一次的文件 ("could not get idle state" 但 rc=0,旧文件还在;`>/dev/null 2>&1` 正好把错误吞掉)。 正解是 run 中用 screencap 截图。这次真机上据此误判过"界面没进运行态" 真机补验(Pixel 5a): - D5':阻塞桩(主线程死睡不看 flag,心跳独立跳)→ 点停止后 1.56s 心跳记下 stopSeenAt, 之后每一拍都带着(sticky 生效),10s 后界面收口并如实报「已停止(引擎未确认收尾)」 —— 证明心跳 ack 这根保险丝端到端是通的,且两段超时的文案能区分是哪一段没等到 - D6:dd 写 800MB 制造 IO 压力,养号跑 34s,心跳间隔始终 2002~2005ms,无一次接近 8s - 设备已还原:产物 md5 与仓库一致,桩/截图/临时入口全部清掉 自检仍全绿:smoke 526 / audit CLEAN / protocol-check 35 / pc-selftest-id 114 / pc-selftest-bridge 45
  • 345182d475 运行期协议 v2:心跳判活 / 启动握手 / 停止两段 界面与引擎之间原来只有"文件 + 超时猜",这次补上真正的运行时协议: 引擎侧 - bridge 新增独立心跳线程,每 2s 整份重写 engine-beat.json(与 run-state 分开写, 两个写者写同一个文件必然互相覆盖)。心跳不调 checkStop / report —— 前者会把 StopSignal 抛进心跳线程,收尾期就再没人写心跳;后者会覆盖主流程的 phase。 stopSeenAt 是 sticky 的,否则下一拍就把停止确认抹掉。 - run-state 增 v / seq / startedAt / engine.task / engine.capabilities.heartbeat - enable 改成"先起心跳、拿结果、再写第一次状态" - main 的 finish 用 try/finally 包住,异常也不会漏掉 heartbeatStop - config 增 runtime.runId 绑定:双方都非空且不一致才拒绝(独立运行必须放行) 界面侧 - pollEngine 重写成四段:终态 → 启动握手 → 停止两段 → 常态判活 - 判活以心跳为主判据,engines.all() 只用于加速判死;心跳新鲜时它说没有也不判死 - 状态条四档:启动中(较慢)/ 运行中 / 正在通知引擎 / 正在收尾 - childAlive 优先按 launch 拿到的子引擎 id 精确匹配,取不到才退回旧宽口径 - 所有超时改从 Protocol.SPEC.thresholds 取,不再有魔法数字 配套 - 两侧 protocol.js(除挂载点外逐字节相同)+ protocol-check.js 强制一致 - 新增 pc-selftest-bridge.js(自建"只登记不执行"的线程桩) - fake-engine 补 v 与心跳,否则最常用的 UI 联调手段会被判成引擎失联 - docs/PROTOCOL.md,AI_CONTEXT 的 §2.3 / §2.4 / §3.x / §4.1 / §11.3 自检:smoke 526 项、audit CLEAN、protocol-check 35 项、 pc-selftest-id 114 项、pc-selftest-bridge 45 项。 真机(Pixel 5a):心跳 2s 稳定、停止 ≤1s 收口、启动超时 15s 触发、 引擎消失 ≤11s 判出、v1 旧产物正常降级(旧心跳被正确忽略)。
  • 7841847982 私信脚本二(自己粉丝私信):从自己的粉丝列表取材 ## 做了什么 `task = "dm"` 现在支持两个脚本,差别只在**人从哪儿来**: s1 已提 UID 私信 → 读 UID 文本(原有) s2 自己粉丝私信 → 打开自己的主页 → 粉丝列表取材(本次) 两者共用后半段编排:前 followMax 个只关注、接着 sendMax 个只发私信(两批不重叠), 每个之后休 rest 秒。s2 要采 `followMax + sendMax` 个人,采够就停。 ## 新增能力 - `tiktok.profileNav()`:底部导航的 Profile 项。只认 `desc === 'Profile'` + 中心在屏幕下缘, 不限定 class(它是 FrameLayout,限定 Button 一个都找不到) - `profile.openOwnProfile(config)`:先 `ensureFeed` 再点 Profile。**必须先回信息流** —— 底部导航只在首页有,停在搜索页/播放页时直接找必然失败 - `dmflow.collectOwnFans(config, need, summary)`:开自己主页 → fans 列表 → `walkList` 收集, 停止判据挂在 `ctx.shouldStop()`(够了就自然结束,不抛异常,已采到的不丢) ## 四个真机坑(三个是新踩的) **① 点完 Profile 1 秒就"就绪",fans 入口却找不到** username 比数字区早得多,而 fans 入口挂在数字上。`settle()` 挡不住(判据是"文案连续两次不变", 加载中与渲染完的签名可能一样)。改用 `profile.waitProfile()`:判据是 username + 关注/粉丝/获赞 三组都读到,读不到只警告不失败。另加"openList 失败 2 秒后重试一次"。 **② 发送键依赖键盘弹起,而 typeInto 的点击有时被输入法吞掉** 文字进去了、键盘没起 → 输入框不缩短 → 那块 72×72 的 ImageView 不存在 → 「输入后找不到发送键」,时好时坏。新增 `dm.ensureSendButton()`:先等 1.5 秒, 拿不到就按输入框中心再点一次强制聚焦,再等 4 秒。 **③ 私信页的脚本卡没有单选互斥** `W.scriptHeader` 只负责画和报状态,互斥是页面的责任,而私信页漏了 —— 两个脚本能同时勾上,`buildDmConfig` 只能挑一个跑:用户以为跑「自己粉丝私信」, 实际跑「已提 UID 私信」,拿一份可能过期的 UID 文件发出去,**界面上看不出任何异常**。 新增 `Pages.toggleDmScript()`,并在 buildDmConfig 里"两个都勾着"时给一条 note。 **④ 休息时间迁移二次失效(v11 补执行)** 9/10 号迁移用 `restMin === 100` 判断,而设备上存的是字符串 `"100"` → 匹配不上 → 迁移"跑了但没改",版本却被抬到 10,**从此永久卡在 100~500**。 症状是「界面写 100~500、引擎按 10~40 跑」。SCHEMA 抬到 11,用 `Number()` 比较补执行一次 (只认那一对精确旧默认值,用户自己调过的不动)。 ## 一个把之前的结论纠正过来的发现 我上次把"推了新版却没生效"归因为"读了 15 小时前的旧 engine-config"—— **那个结论是错的**。 真因是:**AutoX 会按入口脚本路径复用旧代码**。md5 完全一致、时间戳也是新的, 但界面还是旧行为(只渲染一张脚本卡、休息时间仍是 100~500); 把入口 `cp main.js main2.js` 再启动,立刻变成新版。 顺带:设备时区是 PDT,`ls -la` 的 mtime 与主机 `date` 差 15 小时 —— 拿主机时间比设备 mtime 必然得出"这是旧文件"的错误结论。AI_CONTEXT 的 D18 已改写。 ## 真机验证(Pixel 5a / TikTok 47.1.4) ``` 直起引擎(script=s2 / send.max=1 / dryRun) → 生效配置(私信):{"script":"s2","source":"自己的粉丝列表",...} → 点 Profile FrameLayout(972,1871) → 三组数字 3.6s 读全 → openList fans(1.0s)→ 取材 1/1 个(翻 1 屏) → 面板 1.8s 打开 → 写入 "hello" → 发送键 Rect(968,1248,1040,1320) → 「完成:关注 0 个 / 私信 0 条(演练 1 条,未真发)(取材自你自己的粉丝列表,1 人)」 界面点运行 → engine-config:task=dm / script=s2 / uidPath=''/ rest 10000-40000 → 引擎按 s2 执行;因本机没有「随机私信文本」被 validate 拦下(一条都没发) ``` ## 自检 引擎 25 模块 / pc-selftest 114 项;界面 smoke **490 项**(新增 4 条私信相关: 脚本二有引擎标记、script=s2 且 uidPath 为空、说明渲染、**单选互斥**); v10/v9-字符串型存档的迁移断言 5 条;AUDIT_CLEAN;两侧 md5 与设备一致。 ## 文档 - `tiktok-auto/README.md`:3.7 更新(脚本二已实现、迁移 v9/v11 的原委)+ 新增 3.75 - `docs/AI_CONTEXT.md`:D16 补"严格相等 + 版本已抬就再也不跑"、**D18 改写**、 新增 D19(等三组数字)/ D20(单选互斥)/ D21(发送键依赖键盘)
  • c979e40b7a UID私信引擎(task=dm):真机能发出去;关注与私信吃两批不同的人 ## 做了什么 新增 `tiktok-auto/src/dm.js`(发一条私信)+ `dmflow.js`(编排)。 流程按你确认的四条测试策略落地: · 发给**真实目标用户** · 数量 = 界面「私信数量」区间里**每次运行随机取一个数**(不是每日额度) · 文案从「随机私信文本」文件里随机挑 · 失败一律**跳过**(连续 5 个都失败才提前收尾,那说明是环境问题) 「关注数量 100~200」与「私信数量 20~30」是**两批完全不同的人**: 前 follow.max 个只关注,接下来 send.max 个只发私信。 ## 关键发现:发送键在无障碍树里、点得到 这是私信**能做**、而评论做不了的原因。真机锚点: ``` 输入前:输入框 40,1816,960,1904 右侧只有表情按钮 聚焦后:输入框 40,1240,960,1328 (键盘弹起,上移) 输入后:输入框 40,1240,888,1328 ← 宽度缩短 新增 [ImageView] 968,1248,1040,1320 clickable=true ← 发送键 ``` 判据五条(缺一条就点到表情按钮或点空):垂直重叠 / left >= 输入框右边界+10 / 尺寸 40~120 / clickable / desc 不含 stickers|gifs|emoji。取最靠左的那个。 **点击必须用坐标**:它无 id 无 desc,无障碍 ACTION_CLICK 会落到父容器。 ## 真机验证(真的发出去了) ``` 打开主页 → 点 Message(586ms 开面板)→ 写入 "hi" → 定位发送键 Rect(968,1248,1040,1320) → 点它 → 404ms 后输入框清空 → sent=1 → 「完成:关注 0 个 / 私信 1 条」 ``` dryRun 也验证过:输入到位、发送键定位到、清空并收起但不发送。 ## 休息时间默认值 100~500 → 10~40 秒(v9/v10) 它是**每处理完一个 UID 之后**的休息,而两批合计 120~230 人 —— 按旧默认一轮要跑 5~24 小时,实际跑不完(手机过热、被系统冻结、中途断掉这轮就白算)。 改成 10~40 秒后约 175 人 ≈ 73 分钟。 ## 顺带修的两个真 bug **① `MIGRATIONS` 的键写错了**。它的语义是"从哪个版本升上来"(循环是 `for (v = fromVersion; v < SCHEMA; v++) MIGRATIONS[v]`),我最初写成 `9:`, 于是 `fromVersion=8` 查的是不存在的 `MIGRATIONS[8]` → **静默跳过**, 设备被标成 v9 而值仍是旧的。把 SCHEMA 抬到 10、迁移键写 `9:` 补偿执行。 **② `Store.load()` 迁移后不写回存储**。它只返回内存 config、没有 save —— 下次启动又从旧值重新迁移,而且引擎可能拿到"内存已改、存储未改"的两份不一致数据。 在 `Store.init()` 里补一次 `Store.save()`(此时 state 已设好,不会递归)。 另外在 `buildDmConfig` 里加了一道**读取时兜底**:仍是旧默认 100/500 就按 10/40 执行并给 note。 ## 脚本二「自己粉丝私信」未实现 取材链路(从**自己**的粉丝列表抓人)还没做,所以 `DM_SCRIPTS.s2` **刻意没有 engine 标记** —— 点运行会被 `Dialog.engineMissing` 明确拦下,而不是按脚本一的逻辑静默跑 (那会拿自己的粉丝当"已提 UID",结果完全不对)。 ## 自检 引擎 25 模块 / pc-selftest 114 项;界面 smoke **477 项**(新增 14 条:dm 映射、区间随机、 脚本二无引擎标记、prepare 不崩、**旧默认休息兜底**);AUDIT_CLEAN;两侧 md5 与设备一致。 ## 一个必须记住的教训(已写进 AI_CONTEXT D18) **验证配置前先看 `engine-config.json` 的 mtime**。我在这上面浪费了三轮: 反复"验证"迁移没生效,实际读的是 **15 小时前的旧文件** —— 那几次「点运行」根本没触发, 而我只 rm 了 run-log/run-state,没删 engine-config。 **能在 PC 上验的逻辑(配置映射)就用 smoke 断言,别靠真机点按钮。**
  • bc2d03dde7 养号引擎(task=nurture):信息流随机浏览 + 点赞 + 关注;评论如实标注不可用 ## 做了什么 新增 `tiktok-auto/src/nurture.js`:在首页信息流里随机浏览、按概率点赞与关注, 模拟真实活跃度。**没有目标** —— 视频链路是"搜关键词看 N 个",养号是"打开信息流一个接一个刷"。 双约束(谁先到谁停,结果里记 stoppedBy,不笼统说"完成"): · 单次操作 10~30 → nurture.rounds = **轮数**(规格书没写单位,已按你的确认定下来) · 浏览时长 3~8 分钟 → nurture.browse = 墙钟上限 每轮:确认还在 feed → 判内容类型(照片帖没播放,短停留)→ watch 5~25 秒 → 按概率点赞/关注(动作后 0.8~2.5 秒随机停顿)→ 上滑(判据是"新内容真的出现")。 **几乎全是复用**:flow.launchApp / flow.ensureFeed(应用级)、player.watch(有界观看 + 播放存活证据)、interact.like / interact.follow(点一下 + 验状态)、tiktok.feedSignature (判上滑有没有真换视频)。新写的只有编排这一层。 ## 三个必须修的地基 **① `player.watch` 的页面守卫可注入**。`onPlayerPage()` 要求「有返回箭头、没有底部 导航栏」,这两条在信息流上正好相反 —— 默认守卫在 feed 上恒为 false,watch 会在 3 次 采样(约 3 秒)内以 left-player-page 自杀,一个视频都看不完。养号传 `guard: () => pageState() === 'feed'`,视频链路不传、行为完全不变。 **② `panelInput()` 要认"键盘没弹"的形态**。首页信息流里点评论按钮打开面板,输入框 不会自动获得焦点、键盘也就不弹,它停在屏幕底部(实测 y=1816/1920),落不进原来的 0.45~0.85H 区间 → 面板明明开着却判成"没打开"。 **③ 评论计数多了一种格式**。新版 UI 把评论区拆成 Comments / Reviews 两个页签, 文案是 `Comments 785`(数字在后、与页签名同一个 TextView),旧正则 `^\d+\s*comments$` 一条都不匹配。 ## 评论:当前版本做不到(已如实标注,不做静默降级) `commentRate` 一律传 0,界面那行改成「当前版本不支持」,notes 里写明原因。 不是没实现,是**目标在无障碍树里不存在**: · 面板打开后右侧竖排动作栏的节点仍在树里,且与输入框同高 · 把输入框整行右侧的所有节点 dump 过:只有动作栏那六个 + 每条评论自己的赞/表情 + 作者头像,**没有发送键**(截图上那个粉色 ↑ 是自绘的) · 引擎是 execScriptFile 起的**子脚本**:gesture() 无效、shell 无注入权限 (SecurityException)、root shell 报 Error opening shell: 'su' 顺带修掉一个**假阳性**:原来按"输入框下方取最右"找发送键,会稳定命中**点赞按钮** (id=g8g)—— 点它 → 面板收起 + 视频被点赞 → 业务侧判成"评论成功"。 现在排除动作栏(它们的 desc 都有明确前缀)+ 找不到就如实报失败。 这意味着**视频链路的评论也一起失效了**(同一个发送键,TikTok 改版导致的既有回归), 现在的行为是如实报 `send-button-not-found` / `panel-still-open`。 ## 一个会把 App 弄崩的 bug(真机上零提示) `Engine.prepare` 只在 `task === "id"` 时早返回,养号于是落到末尾那句 「关键词为空」的校验上 —— 而养号的配置里**没有 target**(它没有搜索目标), `built.config.target.keyword` 直接 `TypeError`。 在 AutoX 里这个崩溃**完全没提示**:脚本退出、界面回桌面、日志文件一个都没生成。 只有 logcat 能看到 `ScriptEngineService: TypeError ... tiktok-app.js#3270`。 已加分支早返回,并在 smoke 里加了断言防回归(PC 上会得到同一个异常)。 ## 真机验证(Pixel 5a / TikTok 47.1.4) ``` 动作全关 3 轮 → 3 轮跑满;每次 watch 都有音频证据;上滑 916/1036ms 都等到新内容 likeRate=100% → 2 轮 2 次点赞,落在两个不同视频,坐标都在屏内 followRate=100% → 2 轮 2 次关注,都靠「关注按钮消失」验证 界面端到端 → 点运行 → engine-config task=nurture、 rounds 10-30 / browse 180000-480000 / like 0.3 / comment 0 / follow 0.15 → 引擎 ensureFeed → 真的跑起来(16.6s / 21.2s / 22s 三个视频, 上滑 890/918/831ms),跑了 3 轮后因设备无障碍服务掉线中断 (Accessibility service is enabled but not running —— 设备状态问题, 我用 force-stop 反复重启 AutoX 导致的,文档里写了恢复办法) ``` 自检:引擎 114 项 / 界面 smoke **463 项**(新增 18 条)/ AUDIT_CLEAN / 两侧 md5 与设备一致。 ## 文档 - `tiktok-auto/README.md` 新增 3.6 节(双约束 / 守卫为什么必须注入 / 评论为什么做不到 / 已知边界) - `docs/AI_CONTEXT.md` 补 D12~D15(prepare 必须按任务分支、gesture 只在主脚本有效、 发送键不在无障碍树、force-stop 会让无障碍服务掉线并给出恢复命令)

4 時間 前

yuyin333 が dumengxingzhou/tiktok-scripts に新しいブランチ main を作成しました

4 時間 前

yuyin333 がリポジトリ dumengxingzhou/tiktok-scripts を作成しました

4 時間 前