mirror of
https://github.com/OLmatter/glm-coding-helper.git
synced 2026-10-06 15:13:13 +08:00
v23.5: add configurable first-click delay (random range) before clicking captcha
OCR is now so fast (v6 tens of ms) that the first character click can land before the captcha DOM finishes rendering/animating -> first click misses. Previously the inter-click delay only applied between characters; the first click had zero wait. Add a configurable pre-first-click random delay (default 150-300ms): new CAPTCHA_FIRST_CLICK_DELAY_MIN_MS/MAX_MS config, exposed in the config panel under '验证码点字延时策略' as '首击前延时', passed through getCaptchaDirectDelayConfig + normalize, slept at the start of clickCaptchaDirectCoords. Set to 0 to disable.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
## 2026-06-23
|
||||
|
||||
- 发布用户脚本 v23.5:新增「首击前延时」配置。PP-OCRv6 识别太快(几十 ms),识别完瞬间点第一个字时验证码 DOM 可能还没完全渲染/动画到位,导致第一击落空。之前点击间延时只加在字与字之间,第一击前零等待。现在加可配置的首击前随机延时(默认 150-300ms),在配置面板「验证码点字延时策略」下方新增「首击前延时」最小/最大输入框,设为 0 则不等。
|
||||
- 发布用户脚本 v23.4:彻底简化 WAITING 超时逻辑,删除所有验证码状态判断(captchaSeen/计数器/PS.inProgress 分支),兜底超时从 30 秒压到 10 秒。之前的多层判断有遗漏,少数场景会误判"验证码识别中"然后耐心等到 20-30 秒。现在回到最原始逻辑:点击后只看有没有结果(preview 响应/弹窗),10 秒没结果立即重试点订阅。10 秒兜底:正常识别(含老 CPU)5-8 秒够,超 10 秒就是卡住了。
|
||||
- 发布用户脚本 v23.3:修复自动点击订阅后干等到 15 秒超时的问题。之前点击订阅后,若合成 click 事件没触发智谱前端弹验证码(按钮 DOM 已就绪但前端状态机还没准备好),主流程会一直停在 WAITING 干等到 `MODAL_WAIT=15000` 超时,浪费抢购黄金窗口。现在用"验证码 iframe 是否已拿到新 prompt+背景图"作为信号:iframe 脚本每次拿到新验证码(prompt 或背景图变化)时让 GM 计数器 `glm_captcha_seen_seq` 自增,主流程点击时记下基线,WAITING 阶段比对——计数器增长了说明验证码已弹出,耐心等识别;1.5 秒还没增长说明点击没触发验证码,立即回 IDLE 重试点订阅。计数器只增不减、无残留、无时序错乱。
|
||||
- 修复 PS 5.1 中文系统下 `.ps1` 脚本 ParserError("Missing expression after ','"):所有 `.ps1` 加 UTF-8 BOM,避免 PS 5.1 按 GBK 解析 UTF-8 中文字节导致语法解析崩溃。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name 智谱 GLM Coding Plan 抢购助手 + 本地 OCR 自动验证码
|
||||
// @namespace http://tampermonkey.net/
|
||||
// @version 23.4
|
||||
// @version 23.5
|
||||
// @description GLM Coding Rush / 智谱 GLM Coding Plan 抢购助手,一键抢购油猴脚本 / Tampermonkey userscript,配合本地 CPU/GPU OCR 自动识别中文点选验证码并点击,支持多窗口并发、限流重试和支付页安全保护
|
||||
// @author mumumi
|
||||
// @include https://*bigmodel.cn/glm-coding*
|
||||
@@ -609,6 +609,9 @@
|
||||
CAPTCHA_CLICK_DELAY_MIN_MS: 250,
|
||||
CAPTCHA_CLICK_DELAY_MAX_MS: 400,
|
||||
CAPTCHA_CLICK_DELAY_JITTER_PERCENT: 20,
|
||||
// 首击前延迟(验证码 DOM 渲染/动画需要时间,识别太快会导致第一击落空)。随机区间。
|
||||
CAPTCHA_FIRST_CLICK_DELAY_MIN_MS: 150,
|
||||
CAPTCHA_FIRST_CLICK_DELAY_MAX_MS: 300,
|
||||
RUSH_ENABLED : false,
|
||||
RUSH_TARGET_HOUR : 10,
|
||||
RUSH_TARGET_MIN : 0,
|
||||
@@ -1105,6 +1108,9 @@
|
||||
const delayMin = Number.isFinite(parseInt(CFG.CAPTCHA_CLICK_DELAY_MIN_MS, 10)) ? parseInt(CFG.CAPTCHA_CLICK_DELAY_MIN_MS, 10) : 250;
|
||||
const delayMaxRaw = Number.isFinite(parseInt(CFG.CAPTCHA_CLICK_DELAY_MAX_MS, 10)) ? parseInt(CFG.CAPTCHA_CLICK_DELAY_MAX_MS, 10) : 400;
|
||||
const delayMax = Math.max(delayMin, delayMaxRaw);
|
||||
const fcMin = Number.isFinite(parseInt(CFG.CAPTCHA_FIRST_CLICK_DELAY_MIN_MS, 10)) ? parseInt(CFG.CAPTCHA_FIRST_CLICK_DELAY_MIN_MS, 10) : 150;
|
||||
const fcMaxRaw = Number.isFinite(parseInt(CFG.CAPTCHA_FIRST_CLICK_DELAY_MAX_MS, 10)) ? parseInt(CFG.CAPTCHA_FIRST_CLICK_DELAY_MAX_MS, 10) : 300;
|
||||
const fcMax = Math.max(fcMin, fcMaxRaw);
|
||||
if (!document.getElementById('glm-tf-s')) {
|
||||
const s = document.createElement('style'); s.id = 'glm-tf-s';
|
||||
s.textContent = '.tf-item{padding:6px 10px;margin-bottom:4px;border-radius:4px;cursor:pointer;font-size:13px;color:#333;border:1px solid transparent;transition:all .15s}.tf-item:hover{background:#f5f5f5}.tf-item.active{background:#e6f7ff;border-color:#91d5ff;color:#1890ff;font-weight:700}.tf-btn{padding:4px 8px;font-size:10px;cursor:pointer;border:1px solid #d9d9d9;border-radius:4px;background:#fff;color:#555;height:28px;transition:.2s}.tf-btn:hover{border-color:#40a9ff;color:#40a9ff}';
|
||||
@@ -1156,6 +1162,18 @@
|
||||
<input type="number" id="glm-cdmax" value="${delayMax}" min="1" max="10000" style="width:72px;padding:3px 6px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;text-align:center">
|
||||
<span style="font-size:13px;color:#888">ms</span>
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-top:8px">
|
||||
<span style="font-size:13px;color:#666">首击前延时</span>
|
||||
<span title="识别完到点第一个字之间的等待。验证码 DOM 渲染/动画需要时间,OCR 太快会导致第一击落空。设为 0 则不等。随机区间。" style="cursor:help;color:#999;font-size:14px;border:1px solid #ccc;border-radius:50%;width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center;line-height:1">?</span>
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">
|
||||
<span style="font-size:13px;color:#888">最小</span>
|
||||
<input type="number" id="glm-fcdmin" value="${fcMin}" min="0" max="10000" style="width:72px;padding:3px 6px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;text-align:center">
|
||||
<span style="font-size:13px;color:#888">ms</span>
|
||||
<span style="font-size:13px;color:#888">最大</span>
|
||||
<input type="number" id="glm-fcdmax" value="${fcMax}" min="0" max="10000" style="width:72px;padding:3px 6px;border:1px solid #d9d9d9;border-radius:4px;font-size:13px;text-align:center">
|
||||
<span style="font-size:13px;color:#888">ms</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="border-top:1px dashed #eee;padding-top:12px;margin-top:4px"></div>
|
||||
<label style="display:flex;align-items:center;cursor:pointer">
|
||||
@@ -1228,6 +1246,8 @@
|
||||
CAPTCHA_CLICK_DELAY_MIN_MS: parseInt(panel.querySelector('#glm-cdmin').value, 10),
|
||||
CAPTCHA_CLICK_DELAY_MAX_MS: parseInt(panel.querySelector('#glm-cdmax').value, 10),
|
||||
CAPTCHA_CLICK_DELAY_JITTER_PERCENT: CFG.CAPTCHA_CLICK_DELAY_JITTER_PERCENT,
|
||||
CAPTCHA_FIRST_CLICK_DELAY_MIN_MS: parseInt(panel.querySelector('#glm-fcdmin').value, 10),
|
||||
CAPTCHA_FIRST_CLICK_DELAY_MAX_MS: parseInt(panel.querySelector('#glm-fcdmax').value, 10),
|
||||
RUSH_ENABLED: panel.querySelector('#glm-re').checked,
|
||||
RUSH_TARGET_HOUR: parseInt(panel.querySelector('#glm-rh').value, 10),
|
||||
RUSH_TARGET_MIN: parseInt(panel.querySelector('#glm-rm').value, 10),
|
||||
@@ -1598,6 +1618,8 @@
|
||||
maxGapMs: clampCaptchaInt(config.maxGapMs, 1, 10000, 500),
|
||||
jitterPercent: clampCaptchaInt(config.jitterPercent, 0, 1000, 20),
|
||||
stepDelays: stepDelays && stepDelays.length ? stepDelays : null,
|
||||
firstClickMinMs: clampCaptchaInt(config.firstClickMinMs, 0, 10000, 150),
|
||||
firstClickMaxMs: clampCaptchaInt(config.firstClickMaxMs, 0, 10000, 300),
|
||||
};
|
||||
}
|
||||
function getCaptchaDirectDelayConfig() {
|
||||
@@ -1607,6 +1629,8 @@
|
||||
minGapMs: CAPTCHA_CFG.CAPTCHA_CLICK_DELAY_MIN_MS,
|
||||
maxGapMs: CAPTCHA_CFG.CAPTCHA_CLICK_DELAY_MAX_MS,
|
||||
jitterPercent: CAPTCHA_CFG.CAPTCHA_CLICK_DELAY_JITTER_PERCENT,
|
||||
firstClickMinMs: Number.isFinite(parseInt(CAPTCHA_CFG.CAPTCHA_FIRST_CLICK_DELAY_MIN_MS, 10)) ? parseInt(CAPTCHA_CFG.CAPTCHA_FIRST_CLICK_DELAY_MIN_MS, 10) : 150,
|
||||
firstClickMaxMs: Number.isFinite(parseInt(CAPTCHA_CFG.CAPTCHA_FIRST_CLICK_DELAY_MAX_MS, 10)) ? parseInt(CAPTCHA_CFG.CAPTCHA_FIRST_CLICK_DELAY_MAX_MS, 10) : 300,
|
||||
});
|
||||
var override = readCaptchaDirectDelayOverride();
|
||||
if (!override) return baseConfig;
|
||||
@@ -1617,6 +1641,8 @@
|
||||
maxGapMs: override.maxGapMs != null ? override.maxGapMs : baseConfig.maxGapMs,
|
||||
jitterPercent: override.jitterPercent != null ? override.jitterPercent : baseConfig.jitterPercent,
|
||||
stepDelays: Array.isArray(override.stepDelays) ? override.stepDelays : baseConfig.stepDelays,
|
||||
firstClickMinMs: override.firstClickMinMs != null ? override.firstClickMinMs : baseConfig.firstClickMinMs,
|
||||
firstClickMaxMs: override.firstClickMaxMs != null ? override.firstClickMaxMs : baseConfig.firstClickMaxMs,
|
||||
});
|
||||
}
|
||||
function getWindowIndex() {
|
||||
@@ -2292,6 +2318,15 @@
|
||||
var rect = bgEl.getBoundingClientRect();
|
||||
var plan = buildCaptchaDirectClickPlan(rect, result, schedule);
|
||||
console.log('[captcha-direct-page] click result:', JSON.stringify(result).substring(0, 260));
|
||||
// 首击前延迟:验证码 DOM 渲染/动画需要时间,OCR 太快(v6 几十 ms)会导致第一击落空。
|
||||
// 用随机区间,避免固定值被识别为机器。
|
||||
var fcMin = Math.min(schedule.firstClickMinMs || 0, schedule.firstClickMaxMs || 0);
|
||||
var fcMax = Math.max(schedule.firstClickMinMs || 0, schedule.firstClickMaxMs || 0);
|
||||
if (fcMax > 0) {
|
||||
var firstDelay = randCaptchaInt(fcMin, fcMax);
|
||||
console.log('[captcha-direct-page] first-click delay: ' + firstDelay + 'ms');
|
||||
await sleepCaptchaDirectClickGap(firstDelay);
|
||||
}
|
||||
for (var i = 0; i < plan.steps.length; i++) {
|
||||
await runCaptchaDirectClickStep(bgEl, plan.steps[i], i < plan.steps.length - 1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user