157 Commits
Author SHA1 Message Date
OLmatter 9c4745ae22 fix(v23.17): 405 冷却 0=不冷却 现可生效(之前 \&\& 守卫会落到 20000 默认值)
两处 (CFG.RISK_CONTROL_COOLDOWN_MS || 20000) 改成 if (cd > 0) 显式判断。
现在配置为 0 真的能关闭冷却机制,脚本立即重试。
v2026.07.30-1030
2026-07-30 10:27:13 +08:00
OLmatter c1cfa4a6e0 i18n(v23.16): 状态栏中文化——auto-close disabled 提示 2026-07-30 10:23:06 +08:00
OLmatter f4d5faf1fc feat(v23.15): 风控冷却状态栏加可配置入口提示
状态栏显示「🛑 风控冷却中(剩 Xs),可在配置面板「405 风控冷却」调整」,
告诉用户冷却时间在哪改。配置入口:油猴菜单 → 打开配置面板 → 自动关闭
无效支付/限流弹窗下方 → 「405 风控冷却」输入框(默认 20000ms)。
2026-07-30 10:15:28 +08:00
OLmatter d7449a9d0c fix(v23.14): 405 风控冷却优先级 bug——小飞机警告盖过冷却提示
群反馈 9:47 抢购时'小飞机提示脚本不管用'。截图证据:preview 先 200(触发小飞机警告),
后 405(v23.13 识别到了)但状态栏还显示小飞机警告——用户看不到'风控冷却中(剩 Xs)',
以为脚本卡死。

根因:v23.13 只在 1530 路径(isPayDialog + busy/sold_out/risk_control)处理了 risk_control,
1081/1479 路径(isAirplanePayDialog 情况 D warn)没守卫 PS.result,405 走错分支。

修复:
- 1081 检查 hasAirplaneInDialog 时守卫 PS.result !== 'risk_control'
- 1479 WAITING 阶段小飞机警告加 risk_control 守卫
- 1495 路径(isAirplanePayDialog close)补 risk_control 时设 riskCooldownUntil
- 1495 reason 三元加 risk_control 分支显示'🛑 风控拦截(405),关闭弹窗并冷却'

冷却时间 RISK_CONTROL_COOLDOWN_MS 保持可配置(配置面板「405 风控冷却」输入框,默认 20000ms)。
2026-07-30 10:12:02 +08:00
OLmatter ef932668fc feat(#48 #51): 405 风控识别 + 冷却减速机制 (v23.13)
采纳 wang-zhuo996 在 #48 的诊断:preview fetch 拦截只判 body 里的 d.code,
从不看 r.status,405 落入 else 当 busy 处理 → 立即重试越撞越多 WAF 风控。

改动:
- fetch 拦截加 r.status === 405 分支,单独标记 risk_control
- checkPayDialog: risk_control → close(关弹窗)
- 关弹窗分支识别风控,设 riskCooldownUntil = now + 冷却时长
- tick 主循环冷却检查:冷却期内不点订阅,状态栏显示剩余秒数
- DEF 加 RISK_CONTROL_COOLDOWN_MS = 20000(默认 20 秒)
- 配置面板加「405 风控冷却」输入框(0 = 不冷却)

实现采纳诊断但不合 PR #51/#52(#51 自动重登风险高,#52 405→暂停是退步)。
2026-07-28 00:44:34 +08:00
OLmatter aef6ca65e1 fix: 更新 MiniMax 邀请码 IKhXTPYbQC → KkI58QB9Ip
user.js v23.12。邀请码数组拆分改为 ['KkI','58QB','9Ip'],MINIMAX_TOKEN_PLAN_URL
和油猴菜单「打开 MiniMax Token Plan 优惠入口」同步换码。邀请码字符串只在
initMiniMaxTokenPlanEntry 函数内引用,URL 自动注入逻辑不变。
2026-07-28 00:04:41 +08:00
OLmatter 271bee651a docs: README 加 TG 群 + Ledger 姐妹项目引流 (m1_xxxx)
- 顶部横幅补 TG 群链接(跟 ledger 榜单按钮并列)
- 原来裸的群链接美化成「交流群 & 姐妹项目」段落
- 推荐姊妹项目 LLM API Ledger(Coding Plan 横评榜单)
- 强调两个项目共用一个 TG 群 t.me/+s1flX6cpUZ1kM2M1
2026-07-23 02:48:18 +08:00
OLmatter ae9aacae32 docs: 顶部加榜单入口(智谱不放货,引导用户看其他厂商对比) 2026-07-22 23:28:51 +08:00
OLmatter 51d2eafec0 feat(启动脚本): 路径长度主动提示 + 端口占用预检测
- one_click_start.ps1: Warn-LongInstallPath 阈值 70→60(实测 venv 最深 177 字符,
  Root 60 + 177 = 238,留 22 余量给 pip 临时文件);中文化
- one_click_start.ps1: pip 失败分支主动检测路径长度,>60 时中文加粗提示
  '路径偏长,建议移到短路径',不再只显示通用英文
- start_backend.ps1: 启动前检测 8888 是否被占,被占时提示占用进程 PID/名称/路径
  (解决 WinError 10013 无头绪排查问题)
- README 常见问题: 新增'pip 失败/路径太深'和'WinError 10013/端口被占'两条
2026-07-17 21:15:32 +08:00
OLmatter a05d6804e1 docs: 移除'多开几个窗口'建议,改为建议单窗口+按情况调大延时
近期风控严,多开窗口反而触发 RPM 风控
2026-07-09 23:46:42 +08:00
OLmatter a9b749366c docs: 移除'11点前还有机会'过时说法,说明官方近期不放量
- README 风控建议段:'不要过早放弃/11:00前还有机会' → '官方近期不放量,连拼好模活动也取消'
- Greasy Fork 描述:加'官方近期不放量'条目 + 补 v23.11 更新说明
- CHANGELOG 记录本次文档变更
2026-07-09 23:44:00 +08:00
OLmatter de0c2b475b feat: 注释邀请码注入(活动已下线)(#45 后续 v23.11)
邀请码活动下线后,脚本每次打开页面仍注入 ?ic=...&closedialog=true,
导致页面尝试加载已不存在的邀请码活动页。现注释相关逻辑,GLM_CODING_URL
改为纯 https://www.bigmodel.cn/glm-coding。

注释保留的位置(活动恢复时取消注释即可):
- GLM_DISCOUNT_CODE 常量
- 邀请码版 GLM_CODING_URL
- ensureDiscountEntry 函数定义 + 2 处调用(启动 + tick 循环)
- 未登录注册的邀请码引导

同步更新 README、Greasy Fork 描述、userscripts README、CHANGELOG。
2026-07-09 23:05:56 +08:00
OLmatter db4aa20be9 docs: greasyfork-description 同步 Shift+F8 批量暂停/恢复 2026-07-05 22:05:49 +08:00
OLmatter 01c0752987 docs: 同步 Shift+F8 批量暂停/恢复到 README/CHANGELOG/userscripts README
- README.md 快捷键章节加 Shift+F8 条目 + 覆盖范围说明
- CHANGELOG.md 加 2026-07-05 v23.10 条目
- scripts/userscripts/README.md 快捷键列表加 Shift+F8
2026-07-05 22:03:22 +08:00
OLmatter 57d98f9b86 feat: Shift+F8 跨同浏览器窗口批量暂停/恢复 (#45)
保留原 F8 单键行为不变,新增 Shift+F8 批量切换同浏览器所有 glm-coding
普通窗口的暂停状态。

- 新增独立广播 key PAUSE_BROADCAST_KEY,与原持久化 RUNTIME_PAUSE_KEY 分离
  (原 key 负责持久化/新窗口继承暂停态,广播 key 只做实时联动)
- 启动时 GM_addValueChangeListener 监听广播,remote 才响应、防回环
- DEF 加 HOTKEY_PAUSE_ALL='Shift+F8',可配置
- 油猴菜单加'批量暂停/恢复(同浏览器)'项
- 配置面板加批量暂停输入框 + bindHotkeyInput
- setRuntimePaused source 标签中文化(快捷键/批量/远程同步)

覆盖范围:同浏览器普通窗口。跨浏览器/无痕受扩展隔离不支持(设计如此)。

Closes #45
2026-07-05 21:59:05 +08:00
OLmatter 4105dad405 Update README with community links and configuration panel 2026-06-28 03:56:41 +08:00
OLmatter ffabb8f4e8 Modify group chat information in README
Updated group chat link and added official group image.
2026-06-28 03:55:54 +08:00
OLmatter 33238d65fe fix: 清理升级v6时漏改的PP-OCRv5残留默认值 (#42)
setup_backend.py 的GPU冒烟测试还用PP-OCRv5_server_rec(升级v6时漏改),
导致GPU环境装完冒烟测试下载v5而非v6_tiny。另外3个worker文件的环境变量
兜底默认值也是v5(虽运行时被backend_config覆盖成v6,但是隐患):

- setup_backend.py:89 GPU冒烟 PP-OCRv5_server_rec → PP-OCRv6_tiny_rec
- captcha_worker.py:70 OCR_ENGINE_NAME兜底 v5_server → v6_tiny
- ppocr_cpu_pool_worker.py:20-21 fast/fallback v5 → v6_tiny/v6_medium
- ppocr_gpu_worker.py:25 MODEL_NAME兜底 v5_server → v6_tiny

现在所有默认值和backend_config.py的配置一致(都是v6)。fix #42
v2026.06.27-2125
2026-06-27 21:13:01 +08:00
OLmatter 787299b7a6 fix(backend): 预热没预热到OCR - 白图0boxes提前return致首验证码撞JIT丢点
预热本意把yolo+ocr整条链路打热。但白图兜底时YOLO检测0字框就return,
OCR子进程根本没被调用→第一个真验证码仍撞OCR JIT(实测5795ms),
期间客户端等不及、点字没点上(用户报告首图没被点)。

修复:
- captcha_worker.py: YOLO非3boxes时若force_ocr_warmup,强制把图横切3块
  喂OCR跑一次,确保OCR子进程完成JIT预热
- captcha_server.py: 预热调用传force_ocr_warmup=True

实测预热日志现出现 [ppocr-cpu-pool] workers=3 loaded + OCR warmup done,
证明OCR已在预热阶段加载完毕。
2026-06-26 02:05:21 +08:00
OLmatter cf4e594d49 fix(userscript): #40 无效支付页不自动关闭 - 加无金额1.7s兜底 (v23.9)
根因: checkPayDialog 只看接口(busy/sold_out才关),接口success时一律keep,
导致金额为空的无效支付页留着不关——即使开了AUTO_CLOSE_INVALID也没用(该开关
只在verdict=close时生效)。#40用户已开开关仍不关。

修复: 接口非busy/sold_out时读弹窗实际金额:
- 有金额(真支付页)→keep并清计时
- 无金额不立刻关——GLM有时先显示无金额/没抢到、约1s后才弹出真金额订单(#16/#40
  反馈的时序),持续无金额超1.7s宽限期才判无效页close

关键: 不误关真支付页。10个单测覆盖真支付页keep/无金额1s后金额出现keep/
无金额1.7s关/busy直接关/弹窗消失重置计时。

fix #40
v2026.06.26-0145
2026-06-26 01:42:01 +08:00
OLmatter 1e01fad01e fix(userscript): 误把说明文字当点选目标导致后端 0 boxes (v23.8)
后端日志反复 FAIL: detected 0 boxes, need 3。截图显示"识别:验证码"
——根因是 isPointClickPrompt 兜底分支"3-8汉字即合法"太宽,把验证码容器的
说明文字(aria-label=验证码/安全验证/请点击图中文字/点击进行验证等)当成目标
字传给后端,YOLO 在点选图里找不到这些字 → 0 boxes,每分钟轮询反复刷屏。

修复:
- isPointClickPrompt/findPromptText 加说明性文字黑名单(验证码/安全验证/图形验证/
  请点击/完成验证/进行验证/点击图中/点击进行)
- 收紧 in-page [aria-label] 兜底选择器,限定在腾讯验证码容器内
- 真目标字(山水木/请依次点击)不受影响,11个用例全过
v2026.06.26-0135
2026-06-26 01:31:07 +08:00
OLmatter 55ea973095 fix(backend): 启动时清空上次调试图 - 重启即放弃旧图
配合运行时滚动清理(保留最近N个)形成两层:
- 启动 purge_debug_dirs_on_startup(): 清空三目录上次的所有图
  (debug_captcha_direct/auto_captured/ppocr_live_crops),保留_warmup.png
- 运行时 prune_dir(): 连挂几天不重启时滚动保留最近N个

实测本地 logs/ppocr_live_crops 已积累1470个文件,启动清理删1631个归零。
重启即放弃上次调试图(留着占盘没用),连挂几天的用户靠滚动兜底。
v2026.06.26-0125
2026-06-26 01:23:06 +08:00
OLmatter 0213c2ff90 fix(backend): 调试图片无限增长占盘 - 三目录滚动清理
用户反馈长时间挂着抢磁盘被占满。三个调试目录无任何清理:
- dataset/debug_captcha_direct/: 每次 /captcha_direct 都存原图
- dataset/auto_captured/: 截屏图
- logs/ppocr_live_crops/: 每个字裁剪图

现滚动保留最近 N 个(debug 60 / auto_captured 120 / crops 200),
每次写入后清理更老的并打日志。纯调试用途,对识别无影响。
单元测试验证: 按mtime保留最新N个、删老的、杂物不动、二次幂等。
v2026.06.26-0120
2026-06-26 01:18:15 +08:00
OLmatter 2b7de85397 docs: greasyfork 说明加 v23.7 rush 确定修复公告 + 澄清确定按钮行为 2026-06-26 01:11:56 +08:00
OLmatter 85ec6cf7fc fix(userscript): rush 模式 10:00 到点不点确定 - 熔断焊死修复 (v23.7)
根因: PR#36 验证码熔断(防自激振荡)两个缺陷:
1. captchaSession.stopped 置 true 后无任何重置路径(resetCaptchaSession/
   noteCaptchaSuccess 漏清),10:00 前累积 3 次失败即永久焊死,到点不识别
2. 失败计数跨所有图累计,但自激振荡只在同一张图反复开火时发生

修复:
- noteCaptchaFailure 绑定 bgUrl,换图(腾讯SDK重置/新挑战)即重置 failCount/stopped
- rush 黄金窗口(到点后 holdWindowMs 内)失败只冷却不 hard-stop
- resetCaptchaSession + noteCaptchaSuccess 补齐清 stopped/failCount/failBgUrl

保留 PR#36 对同一张图自激振荡的熔断保护,只消除两个副作用。
15 个单元测试覆盖: 同图熔断/换图重置/rush窗口不焊死/窗口外可恢复。
v2026.06.26-0110
2026-06-26 01:08:29 +08:00
OLmatter f24104d322 docs: CHANGELOG 补 PR#36 + PR#37 条目 v2026.06.26-0010 2026-06-26 00:54:21 +08:00
Kang 7979aeab90 fix(macos): validate backend OCR environment before startup (#37) 2026-06-26 00:49:08 +08:00
ygjj 45e9afd78d fix(userscript): 绕开 Chrome LNA + 防止 captcha 死循环自激振荡
本提交叠合两个相关的前端鲁棒性修复,都源自同一个故障复盘(成功几次后
进入 50ms 一发的死循环风暴)。

## 问题一:Chrome 130+ Local Network Access 拦截 fetch

公网 HTTPS 页面(bigmodel.cn)访问本机 loopback(localhost:8888)时,
Chrome 的 LNA 策略会在客户端直接拦截 fetch,根本发不到后端,提示
"Permission was denied for the loopback address space"。

原 `doFetch().catch(() => doGM())` 兜底逻辑虽然能用 GM_xmlhttpRequest
救回来,但每次都浪费 ~200ms 等 fetch 失败、且每次 console 一行红字
噪音、catch 切换瞬间偶尔会撞上业务上下文过期。

修法:localhost 请求**优先走 GM_xmlhttpRequest**(扩展进程,绕过页面
网络栈),fetch 只作为非 Tampermonkey 环境的兜底。同时把 GM onerror
的 [object Object] 改成 status/statusText/error 可读字符串,便于
诊断。补 @connect 127.0.0.1(之前只有 127.0.0.1:8888)。

## 问题二:captcha 状态机的自激振荡死循环

handleCaptchaDirectInPage 的 catch 分支会调用 resetCaptchaSession() 立刻
把 sent 标志清成 false,下一个 50ms tick 立即对同一张图开火,形成
"失败→重置→重打→再失败" 的自激振荡:

- 任何一次瞬时错误(网络、超时、腾讯 SDK 自我刷新换 bgUrl)都会被永久
  放大成持续故障;
- 腾讯 captcha SDK 在被识别为异常流量时会主动重置 widget 换新 bgUrl,
  我们的脚本误以为这是新挑战立刻开打,把后端打爆;
- 同时大量 WebGL context 累积,触发腾讯 SDK 自身的 "Too many active
  WebGL contexts" 警告,雪上加霜。

修法:在 captchaSession 加三道闸门:
1. 单次失败后 1500ms 冷却(inCaptchaCooldown)
2. 连续失败 ≥3 次后彻底熔断停手(isCaptchaStopped),console 打印
   提示用户手动验证 + 刷新页面恢复
3. 成功后清零失败计数(noteCaptchaSuccess),冷却/熔断只追"连续"
   而非"累积"

## 配套文档
README 常见问题加一节 "loopback address space 报错",告诉用户当
GM 通道在某些 Chrome 严苛策略下也被拦时,可以通过 chrome://flags/
#block-insecure-private-network-requests 设为 Disabled 来彻底放行。

## 验证
- 抢购流程跑通后再连续触发 5+ 次验证码,不再出现 "成功几次就开始一直
  报错" 的现象;
- 人为 kill 后端后再触发验证码:失败 1/3 → 冷却 → 失败 2/3 → 冷却 →
  失败 3/3 → 熔断停手,不再 50ms 一发把后端打爆;
- Tampermonkey 环境下 console 不再有 "Permission was denied for
  loopback" 红字。
2026-06-25 05:45:58 +08:00
ygjj 2531183237 fix(backend): 启动时跑一次真推理预热 OCR 模型,避免首请求超时
## 现象
首次启动后端立刻抢购时,第一个验证码识别会失败:浏览器 console 报
"Permission was denied for ... loopback",后端日志报 WinError 10053
(客户端中止已建立连接)。

## 根因
PaddleOCR 首次推理需要 7-12 秒做 JIT 编译(CPU 模式实测 OCR 单步
7.8s + YOLO 等其他几秒)。原 preload_worker 只启动子进程不跑真推理,
"识别子进程就绪" 日志骗了用户——进程就绪 ≠ 模型预热完成。

如果首个验证码请求撞上 JIT 编译,客户端(Tampermonkey GM_xmlhttpRequest
或浏览器 fetch)等不了 12 秒就断开连接,后端推理出结果时 socket 已经
reset,点击错过最佳时机。

后续请求虽然 56ms 就能返回,但腾讯 captcha SDK 可能已经触发自我重置,
导致看上去 "成功几次就不灵"。

## 修法
在 preload_worker 启动子进程后,立即跑一次 dummy 真推理触发完整的
yolo+ocr JIT 编译。优先用 dataset/debug_captcha_direct/ 下已有的真
验证码样本(同尺寸、同分布、JIT 路径最贴近实战),找不到时兜底用全白
480x672 图。

## 验证
- 启动后端,GUI 日志会多出 "模型预热完成 (xxxxms)" 一行
- 立即触发第一个验证码:端到端 50-100ms 完成(vs 修复前 12000ms)
- WinError 10053 不再出现
2026-06-25 05:45:58 +08:00
ygjj 1b1c6b5c0c chore: 规范 captcha_server.py 行尾为 LF 以匹配 .gitattributes
仓库的 .gitattributes 规定 *.py 用 eol=lf,但这个文件的 HEAD 字节实际是
CRLF(历史遗留),导致 git status 永远显示该文件 modified、git diff 永远
看到换行符变更。这里只做一次 CRLF→LF 规范化,无任何代码改动(用
`git diff --ignore-all-space` 验证为 0 行)。
2026-06-25 05:45:58 +08:00
OLmatter c19198b893 fix: map_prompt_to_boxes crash on mismatch - candidate-score fallback instead
When OCR misreads a character (e.g. 钡→部 lookalike) or multi-window requests
cross, prompt chars don't match box chars exactly -> indices_for_prompt raised
RuntimeError -> worker crashed -> captcha failed. Now map_prompt_to_boxes
catches the mismatch and falls back to candidate_scores: each prompt char
picks the box with highest candidate score for that char. Only warns to stderr,
never crashes. Worst case the click order is wrong but the worker stays alive
for the next captcha.
2026-06-24 22:30:25 +08:00
OLmatter 67b23f4883 perf: speed up main-page captcha detection 1200ms -> 200ms
User reported captcha visible but takes very long to reach backend (OCR itself
only 24ms). The main-page captcha IIFE polled every 1200ms, adding up to 1.2s
delay before processing starts. Reduce to 200ms so detection is near-instant.
The iframe IIFE already runs at 50ms; this brings the main-page path in line.
2026-06-24 22:23:03 +08:00
OLmatter 98d5ad09ad fix(gpu): check torch CUDA before setting yolo_device=0, auto-fallback to CPU
paddle GPU available != torch GPU available. User may have GPU paddlepaddle
but CPU-only torch in .venv_paddle_gpu. YOLO/Ultralytics needs torch CUDA,
so device=0 crashes with 'Invalid CUDA device=0 requested, torch.cuda False'.

Now backend_config probes torch.cuda.is_available() separately; if torch has
no CUDA, YOLO silently falls back to CPU (OCR still uses GPU) + prints install
hint. Prevents the hard crash reported by users.
2026-06-24 22:14:38 +08:00
OLmatter f0694ddc37 fix: stop auto-refresh on '抢购人数过多' - manual refresh only to avoid heavier risk control
When all packages show '抢购人数过多,请刷新再试', the script used to
auto-refresh via location.replace - too aggressive, triggers heavier risk
control. Now it stops and tells the user to manually refresh (F5) until they
see the '特惠订阅' button. State set to DONE so the script pauses cleanly;
page reload on manual refresh restarts the scan fresh.
2026-06-24 21:51:36 +08:00
OLmatter 6dd67536d9 docs(faq): add RTX 50 series, GPU troubleshooting, CPU speed FAQ
- RTX 50 (Blackwell) needs CUDA 12.8+ but project uses cu11; use CPU mode
- GPU debugging checklist: paddlepaddle-gpu vs CPU, torch GPU build, driver
- CPU slow? check for old release (v5 server 1189ms vs v6 tiny 110ms)
2026-06-24 21:46:17 +08:00
OLmatter 94886c4ad5 v23.6: recognize '抢购人数过多/刷新再试' as not-buyable (#32); macos tkinter docs (#33)
#32: canBuy/isSoldOut regex was only catching 售罄/补货/暂时; buttons showing
'抢购人数过多,请刷新再试' still passed canBuy -> wasted clicks. Add those +
'请稍后' to the block regex so the script skips and waits instead of clicking
a button that won't go through.

#33: macos-setup.md already had python-tk but framed as optional; Tk is actually
required (one-click-start.command launches a Tk GUI). Reword to make it clear
Tk is required, mention python.org installer bundles tkinter, list the error
messages users see when it's missing.

Also: CRLF fix from earlier, Linux support (PR #34), version bump 23.5 -> 23.6.
2026-06-24 21:20:19 +08:00
OLmatter 0891d18fb6 fix(packaging): force LF for .sh/.command to fix macOS/Linux /bin/bash^M
Root cause (per Dixon): repo had no .gitattributes, so on Windows git checkout
converted shell scripts to CRLF; release zips built on Windows then carried
CRLF -> macOS/Linux users hit /bin/bash^M: bad interpreter.

Fix (two layers):
- Add .gitattributes: *.sh/*.command = eol=lf (force LF on checkout/commit),
  *.ps1/*.cmd = eol=crlf (PS/cmd friendly), JS/py/md = lf, binaries = binary.
- build_release_zips.ps1 / build_portable.ps1: when writing .sh/.command into
  the zip, replace CRLF with LF (defense-in-depth even if autocrlf slipped).
Also normalize scripts/setup_backend_macos.sh (was CRLF in working tree).
Verified: new zips have ALL .sh/.command as LF.
2026-06-24 21:09:07 +08:00
OLmatter 7a5b7a67a4 docs(readme): drop start-backend-pipeline-gui.cmd from file table (not in Win packages)
The file table still listed start-backend-pipeline-gui.cmd but we removed it
from Windows packages to avoid confusion with one-click-start.cmd. Repository
keeps the file for macOS/manual use, but it shouldn't be in the user-facing
file table. Linux entry from PR #34 already present.
2026-06-24 21:00:46 +08:00
hoywu 8457a65b14 docs(setup): document Linux support and ship one-click-start.sh in release zips
The Linux one-click-start.sh and setup_backend_linux.sh scripts landed in
the previous setup commits but were not surfaced in user-facing docs or
in the release zip layout, so Linux users had no on-ramp. This commit
adds the missing user-facing documentation and ships the Linux entry
point in both release zip builders.

- README.md: extend 快速开始 / 启动后端 to cover Linux alongside Windows
  and macOS, update the zip table to mark online-installer as the
  macOS / Linux recommendation, add Linux quick-start snippet, and
  refresh 常用文件 / 常用启动方式 to list one-click-start.sh and the
  new docs/linux-setup.md. Wording tightened so Windows users are not
  told to follow Linux commands and vice versa.
- docs/linux-setup.md: new Chinese-language install guide covering scope,
  prerequisites (Python 3.12 / uv, NVIDIA GPU optional), one-click and
  manual setup paths, virtualenv layout, known limitations, port
  troubleshooting, post-install verification, and a Windows/macOS/Linux
  comparison table.
- one-click-start.sh: refresh the top-of-file comment so it describes
  the actual entry point (start_backend.py --headless ->
  captcha_server_headless) instead of the old "pipeline backend" copy
  from when the Linux path was a stub.
- scripts/release/build_portable.ps1: include one-click-start.sh in the
  portable zip and add a Linux section to the embedded portable README
  pointing users at online-installer for Linux with a fallback chmod +
  run snippet.
- scripts/release/build_release_zips.ps1: include one-click-start.sh in
  the common zip items and rewrite ONLINE_INSTALLER_README.txt to give
  per-platform launch instructions, document auto PyPI mirror detection,
  the .venv_paddle / .venv_paddle_gpu layout, and link to
  docs/linux-setup.md.

No code logic change; only docs + packaging so Linux is a first-class
release target alongside Windows and macOS.
2026-06-24 20:53:24 +08:00
hoywu d7f27554a7 fix(setup): silence prompt on non-tty stdin and emit per-target launch hints
The Linux one-click-start and setup_backend_linux scripts were both
assuming interactive stdin:

- one-click-start.sh called `read -r -p ...` on every fatal exit path
  (non-Linux host, missing release files, install failure, missing
  weight). When the script is launched from a desktop entry, systemd
  user unit, CI, or any other context where stdin is not a TTY, `read`
  would block waiting for input that will never come, hanging the
  process instead of exiting promptly. Replace each site with a small
  `pause_if_tty` helper that only prompts when `[ -t 0 ]`, so the
  script still pauses for a user at a real terminal but returns
  immediately when run unattended.

- scripts/setup_backend_linux.sh printed a single, hard-coded launch
  block that only mentioned `.venv_paddle` (CPU). After the previous
  --target auto/cpu/gpu/both refactor, the user could have built any
  combination of CPU and GPU venvs but the hints always pointed at the
  CPU one. Wrap the post-install message in `print_completion_hints`,
  iterate over the actually-selected modes to print the correct
  `<venv>/bin/python` for each (CPU -> .venv_paddle, GPU ->
  .venv_paddle_gpu), and add an auto-mode command line when both
  venvs exist or a hint to install the CPU fallback when only GPU
  was built.

No behaviour change for the install flow itself; only the prompt
handling and the post-install guidance.
2026-06-24 20:53:24 +08:00
hoywu 8a4e2f364a fix(setup): invoke Linux setup_backend via explicit bash to avoid execute-bit / interpreter issues
Previously invoke_setup splatted the script path with its arguments directly
(""${args[@]}""), which relies on the script having a valid shebang and
the executable bit set when invoked from a different process state or via
some shell wrappers. The Windows Invoke-Bootstrap counterpart launches
its bootstrap via a stable interpreter entry (powershell -File), and the
Linux path should be at least as robust.

- Resolve the setup script to an absolute path under $SCRIPT_DIR and run
  it explicitly with 'bash "$setup_script" "${setup_args[@]}"', so the
  shebang/exec bit is not on the critical path.
- Rename the local array to setup_args / setup_script to make intent
  clearer at the call sites.

This keeps the recreate-on-existing-python behaviour from the previous
fix and matches the Windows pipeline's "stable interpreter invocation"
convention.
2026-06-24 20:53:24 +08:00
hoywu 66f250f7a5 fix(setup): align Linux invoke_setup recreate logic with Windows Invoke-Bootstrap
The Linux one-click-start invoke_setup helper only recreated the venv when
NEEDS_RECREATE was set by the portability/import check. If the target
python (e.g. <venv>/bin/python) already existed from a previous foreign
install or partial state, the setup script would try to reuse it and fail
in confusing ways. This mirrors the Windows Invoke-Bootstrap behaviour.

- invoke_setup now takes the selected venv python as $2, with the recreate
  flag moved to $3 (call sites in the auto/cpu fallback branches updated).
- Recreate is forced when force_recreate=1 OR the target venv python path
  already exists on disk, so any pre-existing python triggers --recreate.
- Comments added in Chinese to match the rest of the Linux script and
  reference the Windows counterpart.

Fixes the case where running one-click-start.sh on a host that already
has a broken/foreign <venv>/bin/python leaves the user with a half-set-up
environment instead of a clean rebuild.
2026-06-24 20:53:24 +08:00
hoywu 5b5b3e2f99 feat(setup): auto-detect available PyPI mirror for Linux install scripts
Linux one-click-start.sh and setup_backend_linux.sh previously installed
dependencies from the default PyPI source, which is often slow or blocked
in mainland China. Mirror the Windows pipeline's PyPI mirror behaviour by
probing well-known mirrors and falling back to the official source.

- New scripts/pypi_mirror.sh: ordered list of Tsinghua / Aliyun / USTC /
  Tencent / pypi.org; pypi_mirror_probe checks each with curl or wget
  (3s timeout); pypi_mirror_select returns the first reachable URL;
  ensure_pypi_mirror_pip_args sets PIP_ARGS=("-i" <url>) only when the
  caller has not already supplied --pip-arg. Reusable via 'source'.
- one-click-start.sh sources pypi_mirror.sh and calls
  ensure_pypi_mirror_pip_args before invoking the backend installer, so a
  bare one-click-start.sh on a CN host picks the fastest mirror.
- scripts/setup_backend_linux.sh does the same for direct invocations
  (e.g. ./scripts/setup_backend_linux.sh), with the same skip-if-pip-arg-
  set semantics. Header comment updated to document the behaviour.

Users who pass --pip-arg keep full control; everyone else gets a working
mirror automatically and the install no longer wedges on pypi.org.
2026-06-24 20:53:24 +08:00
hoywu 08a34ce33b feat(setup): add Linux one-click start and backend setup scripts
Mirror the Windows one-click-start.cmd / setup_backend.ps1 flow for
Linux users:

- scripts/setup_backend_linux.sh: detect NVIDIA GPU, prefer uv for
  Python 3.12 / venv / pip install of requirements-backend-{cpu,gpu}.txt,
  run core-import smoke tests, verify yolo-captcha-detector.pt weight.
  Supports --target auto/cpu/gpu/both, --recreate, --skip-install,
  --no-smoke-test, --pip-arg.

- one-click-start.sh: Linux entry point that picks auto/cpu/gpu venv,
  rebuilds foreign or broken venvs, falls back from GPU -> CPU on auto
  failure, ensures a CPU fallback venv exists alongside GPU, and execs
  scripts/tools/start_backend.py --headless with CNCAPTCHA_PORT and
  CPU/GPU python overrides.

Together with one-click-start.cmd/.command this gives every platform a
single double-click path to a working captcha backend.
2026-06-24 20:53:24 +08:00
OLmatter 2d3440cd4a docs(greasyfork): add 2026-06-23 risk-control advisory to important reminders
Greasy Fork script page description (docs/greasyfork-description.html) is what
users see on the script listing. Add the click-block risk control as the first
item in 重要提醒: blocked -> wait 10s or manually click 特惠订阅, OCR still auto.
One-liner: 订阅入口点不动就手动点特惠订阅,验证码自动打.
2026-06-23 22:28:44 +08:00
OLmatter ee890ff803 docs(userscripts/README): add risk-control advisory + config panel guide
The standalone userscript README had no mention of the 2026-06-23 click-block
risk control or the config panel options. Add:
- Risk control section: blocked click -> wait 10s or manually click 特惠订阅,
  OCR still auto. One-liner: 入口点不动就手动点特惠订阅,验证码自动打.
- Config panel guide: click delay, first-click delay, auto-close, auto-click.
- F8/F9 hotkeys that were missing.
2026-06-23 22:25:23 +08:00
OLmatter 611d66a8dc docs(userscript): mention OCR v6 + risk-control workaround in @description
The @description shows on Greasy Fork/Tampermonkey list and update notices -
first thing users see. Add: (1) PP-OCRv6 in parens, (2) the risk-control
workaround one-liner '订阅入口被风控拦截时手动点特惠订阅即可,验证码自动打'.
2026-06-23 22:23:23 +08:00
OLmatter 7cd1b7be9c docs(readme): add 2026-06-23 click-block risk control advisory
Zhipu upgraded risk control this morning: auto-click subscribe sometimes
blocked/rejected (manual click too), shows block_message. Advisory:
- wait ~10s and retry when blocked
- if auto-click keeps failing, manually click the '特惠订阅' entry
- OCR/captcha solving still fully automatic regardless of how the entry was
  triggered (auto-click and OCR are decoupled)
One-liner: 入口点不动就手动点特惠订阅,验证码自动打。
2026-06-23 22:09:25 +08:00
OLmatter 9de06c1890 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.
2026-06-23 21:30:09 +08:00
OLmatter d0f14e8d29 fix(install): in-process & script.ps1 @args mangled -Target as value, back to & powershell -File
Previous fix (run bootstrap in-process to avoid pipe buffering) broke
parameter binding: '& script.ps1 @argsList' splatting treated '-Target'
as the value of a positional param, not the param name -> ValidateSet
rejected it. Revert to external '& powershell -File bootstrap.ps1 @argsList'
(param binding reliable), drop the | Tee pipe (was the buffer root cause),
let child stdout inherit console directly for real-time pip progress.
2026-06-23 05:54:56 +08:00