|
|
@@ -1,5 +1,5 @@
|
|
|
/*! tiktok-auto v1.0.0
|
|
|
- * built 2026-10-20T03:13:58.647Z
|
|
|
+ * built 2026-10-20T08:08:36.158Z
|
|
|
* modules: logger, bridge, config, wait, layout, ui, popups, tiktok, player, comment, flow, parse, uidset, filters, profile, idsource, idflow, main
|
|
|
* 由 tools/build.js 自动生成 —— 请不要直接编辑本文件,改 src/ 后重新构建。
|
|
|
*/
|
|
|
@@ -4709,8 +4709,33 @@ TikTokAuto.profile = (function () {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- /** 列表当前可见的每一行(已按屏幕从上到下排序) */
|
|
|
+ /**
|
|
|
+ * 当前在不在"一个可以逐行取 uid 的列表页"上。
|
|
|
+ *
|
|
|
+ * 有两种,长得不一样、资源 id 也不同,但对上层来说都是"一屏一屏的用户行":
|
|
|
+ * · `user-list` 粉丝/关注列表(`txt_desc` 装 uid)
|
|
|
+ * · `users-results` 搜索结果的用户页签(`tv_username` 装 uid)
|
|
|
+ * 上层不该关心是哪种 —— 这正是这个判据存在的意义。
|
|
|
+ */
|
|
|
+ function isListPage(state) {
|
|
|
+ var now = state || where();
|
|
|
+ return now === 'user-list' || now === 'users-results';
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 列表当前可见的每一行(已按屏幕从上到下排序)。
|
|
|
+ *
|
|
|
+ * ★ **按当前页面选解析器**,这是实测踩出来的一个"看起来能跑但永远 0 行"的 bug:
|
|
|
+ * 当初这里写死成 `userListRows()`(粉丝列表的解析器,找 `txt_desc`),
|
|
|
+ * 而搜索结果页的用户行是 `tv_username` —— 于是"取材=搜索结果"时,
|
|
|
+ * 上一步 `usersResultRows()` 明明读到了行(日志里 `userRows` 就绪),
|
|
|
+ * 下一步 `listRows()` 却返回空,最后表现为"处理 0 行、一个都没抓到"。
|
|
|
+ * 两种页面的行结构不同,但**对调用方是同一件事**,所以分派必须留在这里。
|
|
|
+ */
|
|
|
function listRows() {
|
|
|
+ if (where() === 'users-results') {
|
|
|
+ return TikTokAuto.tiktok.usersResultRows();
|
|
|
+ }
|
|
|
return TikTokAuto.tiktok.userListRows();
|
|
|
}
|
|
|
|
|
|
@@ -4775,24 +4800,25 @@ TikTokAuto.profile = (function () {
|
|
|
TikTokAuto.ui.tapPoint(row.x, row.y);
|
|
|
}
|
|
|
|
|
|
- /** 从用户主页退回列表(列表位置会保持,实测) */
|
|
|
+ /** 从用户主页退回列表(列表位置会保持,实测);两种列表页都认 */
|
|
|
function backToList() {
|
|
|
var step = 'backToList';
|
|
|
- var deadline = Date.now() + 8000;
|
|
|
+ var deadline = Date.now() + 10000;
|
|
|
while (Date.now() < deadline) {
|
|
|
var state = where();
|
|
|
- if (state === 'user-list') {
|
|
|
+ if (isListPage(state)) {
|
|
|
return true;
|
|
|
}
|
|
|
- if (state === 'profile' || state === 'comment-panel' || state === 'users-results') {
|
|
|
+ if (state === 'profile' || state === 'comment-panel') {
|
|
|
TikTokAuto.ui.goBack(step);
|
|
|
settle(2000);
|
|
|
continue;
|
|
|
}
|
|
|
- /* 其它页面(搜索/结果/信息流):已经退过头了 */
|
|
|
+ /* 已经退到搜索页/结果页/信息流:说明退过头了(列表已经不在栈上)。
|
|
|
+ * 这种情况不该再往回退 —— 再退就退到首页去了。 */
|
|
|
return false;
|
|
|
}
|
|
|
- return where() === 'user-list';
|
|
|
+ return isListPage();
|
|
|
}
|
|
|
|
|
|
/** 从列表退回用户主页 */
|
|
|
@@ -4854,6 +4880,7 @@ TikTokAuto.profile = (function () {
|
|
|
openList: openList,
|
|
|
switchListTab: switchListTab,
|
|
|
listRows: listRows,
|
|
|
+ isListPage: isListPage,
|
|
|
scrollList: scrollList,
|
|
|
openRow: openRow,
|
|
|
backToList: backToList,
|
|
|
@@ -4945,11 +4972,12 @@ TikTokAuto.idsource = (function () {
|
|
|
var rows = TikTokAuto.profile.listRows();
|
|
|
if (rows.length === 0 && screens === 1) {
|
|
|
/* 首屏还在加载。**等一次**再判定,否则会把"慢"当成"空":
|
|
|
- * 从用户页点开粉丝列表后,页签先出来、行后出来(实测差 1~2 秒),
|
|
|
- * 这时 listRows() 返回空数组 —— 直接 break 就等于"一条都没抓到"。 */
|
|
|
+ * 从用户页点开粉丝列表、或从结果页切到用户页签后,
|
|
|
+ * 容器先出来、行后出来(实测差 1~2 秒),这时 listRows() 返回空数组 ——
|
|
|
+ * 直接 break 就等于"一条都没抓到"。 */
|
|
|
TikTokAuto.wait.waitFor('listRows', function () {
|
|
|
return TikTokAuto.profile.listRows().length > 0 ? true : null;
|
|
|
- }, 8000, 300);
|
|
|
+ }, ctx.config ? ctx.config.timeouts.pageReadyMs : 8000, 300);
|
|
|
rows = TikTokAuto.profile.listRows();
|
|
|
}
|
|
|
if (rows.length === 0) {
|
|
|
@@ -5592,10 +5620,13 @@ TikTokAuto.idflow = (function () {
|
|
|
}
|
|
|
|
|
|
/* 从列表行点进去最快(且实测返回后列表位置保持)。
|
|
|
- * ★ 点开失败时**不再退回搜索**:在列表遍历中途跳去搜索,
|
|
|
- * 会把"当前在哪个列表的第几行"整个丢掉,之后再也接不回原来的列表。
|
|
|
- * 这里直接返回 null,由 judge 按"读不到资料"拦下并记日志。 */
|
|
|
- if (row.node && row.x !== undefined && profileApi.where() === 'user-list') {
|
|
|
+ * ★ 判据是"当前在**任一**种列表页上",不是只有粉丝列表:
|
|
|
+ * 搜索结果的用户列表也一样能直接点行进去。
|
|
|
+ * 早先写死成 `where() === 'user-list'`,于是搜索取材时
|
|
|
+ * 每个候选都要**重新搜一次**(约 15 秒/个)—— 慢十倍且没有必要。
|
|
|
+ * ★ 点开失败时不再退回搜索:在列表遍历中途跳去搜索,
|
|
|
+ * 会把"当前在哪个列表的第几行"整个丢掉,之后再也接不回原来的列表。 */
|
|
|
+ if (row.node && row.x !== undefined && profileApi.isListPage()) {
|
|
|
if (profileApi.openRow(row)) {
|
|
|
summary.openedProfiles += 1;
|
|
|
var data = profileApi.readProfile();
|
|
|
@@ -5751,6 +5782,12 @@ TikTokAuto.idflow = (function () {
|
|
|
/* —— 第二层:深度展开 ——
|
|
|
* 与第一层分开跑,是为了避免嵌套列表上下文(见 idsource.js 文件头)。
|
|
|
* 展开进来的人**同样要过一遍过滤** —— 否则"粉丝的粉丝"会绕过所有条件。 */
|
|
|
+ if (expandQueue.length > 0 && shouldStop() && limitReached()) {
|
|
|
+ /* 上限在主层就满了 → 展开根本没跑。这必须说出来:
|
|
|
+ * 用户明明勾了「再取粉丝列表」,看到"提取满 3 个"很容易以为展开做了。 */
|
|
|
+ summary.warnings.push('提取上限已到,深度展开(再取粉丝列表)本次没有执行');
|
|
|
+ log.warn('idflow', '提取上限已到,' + expandQueue.length + ' 个待展开的账号本次没有展开');
|
|
|
+ }
|
|
|
if (expandQueue.length > 0 && !shouldStop()) {
|
|
|
log.step('idflow', '开始深度展开:' + expandQueue.length + ' 个账号');
|
|
|
for (var e = 0; e < expandQueue.length; e += 1) {
|