koishi-plugin-xlon 1.0.2 → 1.0.3
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/lib/index.js +43 -6
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -114,12 +114,12 @@ async function expandShortLink(ctx, url) {
|
|
|
114
114
|
maxRedirects: 0,
|
|
115
115
|
validateStatus: /* @__PURE__ */ __name(() => true, "validateStatus")
|
|
116
116
|
});
|
|
117
|
-
const
|
|
118
|
-
return
|
|
117
|
+
const location2 = res?.headers?.location;
|
|
118
|
+
return location2 || url;
|
|
119
119
|
} catch (err) {
|
|
120
120
|
try {
|
|
121
|
-
const
|
|
122
|
-
return
|
|
121
|
+
const location2 = err?.response?.headers?.location;
|
|
122
|
+
return location2 || url;
|
|
123
123
|
} catch (_) {
|
|
124
124
|
return url;
|
|
125
125
|
}
|
|
@@ -439,6 +439,43 @@ function buildVxApiUrl(tweetUrl) {
|
|
|
439
439
|
return tweetUrl.replace(/(twitter\.com|x\.com)/i, "api.vxtwitter.com");
|
|
440
440
|
}
|
|
441
441
|
__name(buildVxApiUrl, "buildVxApiUrl");
|
|
442
|
+
async function diagnosePage(page) {
|
|
443
|
+
return await page.evaluate(() => {
|
|
444
|
+
const url = location.href;
|
|
445
|
+
const title = document.title || "";
|
|
446
|
+
const bodyText = (document.body && document.body.innerText || "").slice(0, 600);
|
|
447
|
+
let reason = "页面未渲染出推文(可能网络缓慢或 X 页面结构变化)";
|
|
448
|
+
const isLoginWall = /\/i\/flow\/login|\/login|\/i\/flow\/single-sign-on/i.test(url) || !!document.querySelector('input[autocomplete="username"]') || /^(log in|登录|登入|sign in)/i.test(title.trim());
|
|
449
|
+
if (isLoginWall) {
|
|
450
|
+
reason = "Cookie(auth_token) 可能已失效,被重定向到登录页,请更新 cookies 配置";
|
|
451
|
+
} else if (/rate limit|too many requests|请求过于频繁|尝试次数过多/i.test(bodyText)) {
|
|
452
|
+
reason = "触发限流(Rate limit),请调大 updateInterval 或更换账号";
|
|
453
|
+
} else if (/account doesn.?t exist|账号不存在|這個帳號不存在|user not found/i.test(bodyText)) {
|
|
454
|
+
reason = "账号不存在或用户名拼写有误";
|
|
455
|
+
} else if (/suspended|账号已被冻结|帳號已遭凍結/i.test(bodyText)) {
|
|
456
|
+
reason = "账号已被冻结(suspended)";
|
|
457
|
+
} else if (/something went wrong|出错了|发生了一些错误|重试/i.test(bodyText)) {
|
|
458
|
+
reason = "X 返回错误页(Something went wrong),通常为临时故障或限流";
|
|
459
|
+
}
|
|
460
|
+
return { url, reason };
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
__name(diagnosePage, "diagnosePage");
|
|
464
|
+
async function waitForArticle(page, timeout = 3e4) {
|
|
465
|
+
const outcome = await Promise.race([
|
|
466
|
+
page.waitForSelector("article", { timeout }).then(() => "article").catch(() => null),
|
|
467
|
+
page.waitForFunction(
|
|
468
|
+
() => /\/i\/flow\/login|\/login|\/i\/flow\/single-sign-on/i.test(location.href) || !!document.querySelector('input[autocomplete="username"]'),
|
|
469
|
+
{ timeout }
|
|
470
|
+
).then(() => "login").catch(() => null)
|
|
471
|
+
]);
|
|
472
|
+
if (outcome === "article") return;
|
|
473
|
+
const diag = await diagnosePage(page).catch(() => null);
|
|
474
|
+
throw new Error(
|
|
475
|
+
diag ? `未加载到推文(${diag.reason})| URL: ${diag.url}` : "未加载到推文(页面状态未知)"
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
__name(waitForArticle, "waitForArticle");
|
|
442
479
|
async function screenshotTweetArticle(page, selector = 'article[data-testid="tweet"]') {
|
|
443
480
|
const element = await page.waitForSelector(selector, { timeout: 15e3 });
|
|
444
481
|
if (!element) throw new Error("未能找到推文容器");
|
|
@@ -557,7 +594,7 @@ var XFetcher = class {
|
|
|
557
594
|
});
|
|
558
595
|
await preparePage(page, this.config.cookies);
|
|
559
596
|
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 6e4 });
|
|
560
|
-
await page
|
|
597
|
+
await waitForArticle(page, 3e4);
|
|
561
598
|
const result = await page.evaluate(() => {
|
|
562
599
|
const articles = Array.from(document.querySelectorAll("article"));
|
|
563
600
|
const collected = [];
|
|
@@ -641,7 +678,7 @@ var XFetcher = class {
|
|
|
641
678
|
});
|
|
642
679
|
await preparePage(page, this.config.cookies);
|
|
643
680
|
await page.goto(tweetUrl, { waitUntil: "networkidle2", timeout: 6e4 });
|
|
644
|
-
await page
|
|
681
|
+
await waitForArticle(page, 3e4);
|
|
645
682
|
protectedAccount = await page.evaluate(() => {
|
|
646
683
|
return !!(document.querySelector('[data-testid="icon-lock"]') || document.querySelector('[aria-label*="rotect"]') || document.querySelector('[aria-label*="保护"]') || document.querySelector('[aria-label*="保護"]'));
|
|
647
684
|
});
|