From f62df26ec085d9d20aa875bf20c202e7a20f7afb Mon Sep 17 00:00:00 2001 From: hermes Date: Thu, 27 Aug 2026 03:27:21 +0000 Subject: [PATCH] =?UTF-8?q?v1.2=20=E7=99=BB=E5=BD=95=E7=9B=91=E5=90=AC?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=A4=8D=E5=B7=A5:=20=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E5=A4=B1=E6=95=88/=E8=A2=AB=E9=A1=B6=E5=8F=B7=E5=91=8A?= =?UTF-8?q?=E8=AD=A6=E5=90=8E=E6=AF=8F30=E7=A7=92=E6=A3=80=E6=B5=8B?= =?UTF-8?q?=E6=89=AB=E7=A0=81(=E6=9C=80=E5=A4=9A=E8=87=B3=E5=8C=97?= =?UTF-8?q?=E4=BA=AC17:30),=20=E6=A3=80=E6=B5=8B=E5=88=B0=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=88=90=E5=8A=9F=E8=87=AA=E5=8A=A8=E9=87=8D=E5=90=AF?= =?UTF-8?q?=E7=AD=9B=E9=80=89=E6=89=B9=E6=AC=A1,=20=E6=97=A0=E9=9C=80?= =?UTF-8?q?=E4=BA=BA=E5=B7=A5=E5=86=8D=E5=8F=AB=E5=90=AF=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/daily-runner.js | 56 ++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/scripts/daily-runner.js b/scripts/daily-runner.js index 0b84c99..54b1b63 100644 --- a/scripts/daily-runner.js +++ b/scripts/daily-runner.js @@ -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();