v1.2 登录监听自动复工: 登录失效/被顶号告警后每30秒检测扫码(最多至北京17:30), 检测到登录成功自动重启筛选批次, 无需人工再叫启动
This commit is contained in:
+47
-9
@@ -33,7 +33,7 @@ const log = (m) => console.log(`[daily-runner ${ACCT}] ${new Date().toISOString(
|
||||
// ---------- 工具 ----------
|
||||
const bjNow = () => new Date(Date.now() + 8 * 3600 * 1000); // 北京时间
|
||||
const bjHm = () => { const d = bjNow(); return d.getUTCHours() * 60 + d.getUTCMinutes(); };
|
||||
const pastCutoff = () => bjHm() >= 18 * 60; // 北京 18:00
|
||||
const pastCutoff = (atMin = 18 * 60) => bjHm() >= atMin; // 默认北京 18:00,可传其它时刻
|
||||
const today = () => bjNow().toISOString().slice(0, 10);
|
||||
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
|
||||
const randInt = (a, b) => a + Math.floor(Math.random() * (b - a + 1));
|
||||
@@ -171,6 +171,33 @@ function statusText(s) {
|
||||
return '✅ 在线';
|
||||
}
|
||||
|
||||
// 登录监听:告警发出后每30秒检查登录页是否已被扫码登录(跳回推荐页/出现卡片)
|
||||
// 监听到登录成功 → 自动重启筛选批次;17:30 后不再等(留给18:05收队收尾)
|
||||
async function waitForRelogin() {
|
||||
const pw = require('playwright-core');
|
||||
log('进入登录监听(每30秒检测扫码,最多等到北京17:30)...');
|
||||
writeState('waiting_relogin', null);
|
||||
while (!fs.existsSync(STOP_FLAG) && !pastCutoff(17.5 * 60)) {
|
||||
await new Promise(r => setTimeout(r, 30000));
|
||||
let logged = false;
|
||||
try {
|
||||
const b = await pw.chromium.connectOverCDP(`http://127.0.0.1:${PORT}`);
|
||||
const p = b.contexts()[0]?.pages().find(x => /zhaopin\.com/.test(x.url()));
|
||||
if (p) {
|
||||
logged = await p.evaluate(() =>
|
||||
!location.href.includes('passport') &&
|
||||
!/账号已在其他设备或浏览器登录/.test(document.body?.innerText || '') &&
|
||||
document.querySelectorAll('.recommend-item').length > 0
|
||||
).catch(() => false);
|
||||
}
|
||||
try { await b.close(); } catch (_) {}
|
||||
} catch (_) { /* CDP暂时不通就下轮再查 */ }
|
||||
if (logged) { log('🎉 检测到已扫码登录,自动复工'); return true; }
|
||||
}
|
||||
log('登录监听结束(到时或被叫停),今日不再复工');
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------- 主流程 ----------
|
||||
(async () => {
|
||||
log(`启动 | 端口${PORT} | 库${DB} | 截止北京18:00`);
|
||||
@@ -187,6 +214,8 @@ function statusText(s) {
|
||||
}
|
||||
|
||||
let lastChatLeft = null, zeroStreak = 0;
|
||||
let needRelogin = false; // v1.2:登录类异常(登录失效/被顶号)→ 告警后进监听等扫码,扫完自动复工
|
||||
|
||||
while (true) {
|
||||
// v1.1:随时叫停——每轮检查停止旗标,优雅退出(不发日报不发告警,等重启或18点兜底)
|
||||
if (fs.existsSync(STOP_FLAG)) {
|
||||
@@ -198,25 +227,34 @@ function statusText(s) {
|
||||
|
||||
const { code, out } = await runBatch();
|
||||
|
||||
// 被顶号(账号在其他设备登录)→ 群告警+二维码(会话已被踢,重新登录同样需要扫码),立即结束(2026-08-27)
|
||||
// 被顶号(账号在其他设备登录)→ 群告警+二维码,进登录监听(2026-08-27)
|
||||
if (/账号被顶/.test(out)) {
|
||||
await notifyKickedOut(lastChatLeft);
|
||||
break;
|
||||
needRelogin = true;
|
||||
}
|
||||
// 登录失效 → 群告警(带登录二维码),结束
|
||||
if (/登录已失效|passport\.zhaopin\.com/.test(out)) {
|
||||
// 登录失效 → 群告警(带登录二维码),进登录监听
|
||||
else if (/登录已失效|passport\.zhaopin\.com/.test(out)) {
|
||||
notifyLoginExpired();
|
||||
maybeSendReport('login_expired', lastChatLeft);
|
||||
break;
|
||||
needRelogin = true;
|
||||
}
|
||||
// 风控/验证码 → 私聊告警,结束
|
||||
if (/ALERT.*(风控|验证|频繁|受限)/.test(out)) {
|
||||
// 风控/验证码 → 私聊告警,结束(不监听,风控需人工评估)
|
||||
else if (/ALERT.*(风控|验证|频繁|受限)/.test(out)) {
|
||||
send(DM, `🚨 ${ACCT} 触发风控/验证码(${(out.match(/ALERT[::][^\n]*/) || ['未知原因'])[0]}),今日筛选中止`);
|
||||
maybeSendReport('alert', lastChatLeft);
|
||||
break;
|
||||
}
|
||||
// 聊天耗尽 → 结束
|
||||
if (/聊天次数耗尽/.test(out)) { log('聊天次数耗尽,收工'); maybeSendReport('chat_exhausted', 0); break; }
|
||||
else if (/聊天次数耗尽/.test(out)) { log('聊天次数耗尽,收工'); maybeSendReport('chat_exhausted', 0); break; }
|
||||
|
||||
// v1.2:登录类异常 → 监听扫码,登录成功自动复工;没登录就今日收工
|
||||
if (needRelogin) {
|
||||
needRelogin = false;
|
||||
const relogged = await waitForRelogin();
|
||||
if (!relogged) break;
|
||||
writeState('running', lastChatLeft); // 复工
|
||||
continue;
|
||||
}
|
||||
|
||||
// 解析剩余次数
|
||||
const m = [...out.matchAll(/聊天剩余[::]?\s*(\d+)\s*次/g)].pop();
|
||||
|
||||
Reference in New Issue
Block a user