diff --git a/glm-rush-v4.user.js b/glm-rush-v4.user.js index 97b0248..26796ed 100644 --- a/glm-rush-v4.user.js +++ b/glm-rush-v4.user.js @@ -91,7 +91,7 @@ }; function setState(patch) { - state = { ...state, ...patch }; + Object.assign(state, patch); refreshUI(); } @@ -338,7 +338,8 @@ setState({ stats: { ...state.stats, errors: state.stats.errors + failedResults.length } }); const networkErrors = reasons.filter(r => r.startsWith('网络')).length; - consecutiveErrors = networkErrors === batchSize ? consecutiveErrors + 1 : 0; + consecutiveErrors = (networkErrors > 0 && networkErrors === failedResults.length) + ? consecutiveErrors + 1 : 0; // 连续网络错误 → 暂停 if (consecutiveErrors >= 3) { @@ -354,8 +355,8 @@ return { ok: false }; } - // 只有 429(限流)才退避,555 和 EXPIRE 无延迟立即重试 - if (reasons.every(r => r === 'EXPIRE' || r === '系统繁忙' || r === '555')) continue; + // 只有 429(限流)才退避,EXPIRE 和系统繁忙无延迟立即重试 + if (reasons.every(r => r === 'EXPIRE' || r === '系统繁忙')) continue; // 限流检测 (独立计数) if (reasons.some(r => r.includes('429') || r.includes('限流'))) { @@ -367,9 +368,6 @@ throttleCount = 0; } - // EXPIRE → 立即重试不等待 - if (reasons.every(r => r === 'EXPIRE')) continue; - // 前20秒全速冲,之后才考虑降速 const elapsedSec = (performance.now() - state.stats.startTime) / 1000; @@ -398,25 +396,29 @@ // 自适应延迟 const d = getDelay(roundNum); if (d > 0) await sleep(d); + + // 超过 maxRetry 且在5分钟内 → 切捡漏模式 + if (totalAttempt >= CFG.maxRetry) { + const elapsedSec2 = (performance.now() - state.stats.startTime) / 1000; + if (elapsedSec2 < 300) { + log('进入捡漏模式,降速等待退票...'); + CFG._savedConcurrency = CFG.concurrency; + CFG._savedMaxRetry = CFG.maxRetry; + CFG.concurrency = 2; + CFG.slowDelay = 3000; + CFG.maxRetry = totalAttempt + 200; + continue; + } else { + setState({ status: 'failed' }); + CFG.concurrency = CFG._savedConcurrency ?? CFG.concurrency; + CFG.maxRetry = CFG._savedMaxRetry ?? CFG.maxRetry; + log(`达到上限 ${CFG._savedMaxRetry ?? CFG.maxRetry} 次`); + return { ok: false }; + } + } } - if (!stopRequested) { - const elapsed = (performance.now() - state.stats.startTime) / 1000; - if (elapsed < 300) { - log('进入捡漏模式(10:00-10:05),降速等待退票...'); - CFG._savedConcurrency = CFG.concurrency; - CFG.concurrency = 2; - CFG.slowDelay = 3000; - // 继续循环不走 else - } else { - setState({ status: 'failed' }); - CFG.concurrency = CFG._savedConcurrency ?? CFG.concurrency; - } - } else { - CFG.concurrency = CFG._savedConcurrency ?? CFG.concurrency; - } return { ok: false }; - })(); try { return await _retryLock; } finally { _retryLock = null; } @@ -486,19 +488,20 @@ const ct = resp.headers.get('content-type') || ''; if (ct.includes('application/json')) { const text = await resp.text(); - if (/"isSoldOut":true|"soldOut":true|"isServerBusy":true/.test(text)) { - const patched = text - .replace(/"isSoldOut":true/g, '"isSoldOut":false') - .replace(/"soldOut":true/g, '"soldOut":false') - .replace(/"isServerBusy":true/g, '"isServerBusy":false') - .replace(/"stock":0/g, '"stock":999'); - return new Response(patched, { + const needsPatch = /"isSoldOut":true|"soldOut":true|"isServerBusy":true|"stock":0/.test(text); + if (!needsPatch) { + return new Response(text, { status: resp.status, statusText: resp.statusText, headers: resp.headers, }); } - return new Response(text, { + const patched = text + .replace(/"isSoldOut":true/g, '"isSoldOut":false') + .replace(/"soldOut":true/g, '"soldOut":false') + .replace(/"isServerBusy":true/g, '"isServerBusy":false') + .replace(/"stock":0/g, '"stock":999'); + return new Response(patched, { status: resp.status, statusText: resp.statusText, headers: resp.headers, @@ -786,6 +789,7 @@ function stopAll() { stopRequested = true; + if (window._glmRafCancelled) window._glmRafCancelled(); _activeControllers.forEach(ac => { try { ac.abort(); } catch {} }); _activeControllers = []; setState({ proactive: false, status: 'idle', count: 0 }); @@ -836,9 +840,12 @@ log(`已过${CFG.rushTime} ${passedSec.toFixed(0)}秒, 立即开抢!`); startProactive(); } else { + // 超过30秒,顺延至明天 log(`今天${CFG.rushTime}已过, 明天自动抢购`); + target.setDate(target.getDate() + 1); + log(`顺延至明天 ${CFG.rushTime}`); } - return; + // 如果是顺延情况,继续往下设定定时 } // 未到时间 → 自动设定定时 @@ -869,16 +876,17 @@ // 精确等待: 用 setInterval 10ms 检查, 到时间立即启动 const preAdvanceMs = (CFG.preAdvanceSec || 0) * 1000; + let rafCancelled = false; + window._glmRafCancelled = () => { rafCancelled = true; }; const checkInterval = setInterval(() => { const remaining = target.getTime() - getServerNow(); if (remaining <= preAdvanceMs) { clearInterval(checkInterval); startProactive(); - } - // 额外:在剩余1秒内用 requestAnimationFrame 做最后精确对齐 - if (remaining > 0 && remaining <= 1000) { + } else if (remaining > 0 && remaining <= 1000) { clearInterval(checkInterval); function rafWait() { + if (rafCancelled || stopRequested) return; if (target.getTime() - getServerNow() <= preAdvanceMs) { startProactive(); } else {