sync: dev to extern-contrib - #1022
github-actions[bot] wants to merge 18 commits into
Conversation
回退路径本身可以解析出真实题号,问题在 POST 之后:内层 fetch 只把响应
console.log 掉,从不判断成功与否,随后外层无条件覆盖成"提交失败"。日志里
那次回退实际收到的是 XMOJ 的提交冷却页(`请勿重复提交`,HUSTOJ 的
$OJ_SUBMIT_COOLDOWN_TIME 默认 5 秒,XMOJ 渲染成页面而非 302),响应被丢掉,
所以状态里没有任何提交记录。
- 把回退逻辑抽成 SubmitToEndedContestProblem,返回 {Success, Message}
- 只把 redirected 当成功信号,成功后 return,不再被外层覆盖
- 遇到 `请勿重复提交` 等冷却过去后重试(3 秒一次,最多 5 次)
- 其余失败从响应的 .jumbotron 取服务端原文,不再显示通用报错
- 遇到 `验证码错误` 立即刷新验证码并停止重试(答案已被消耗)
- 题号改用 /\d+/ 提取,原 substring(2, 6) 会把 5 位题号截成 4 位
- 补齐缺失的 GetCaptchaParameter(),并在解析失败时恢复提交按钮
Closes #1017
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
冷却等待期间验证码输入框和刷新按钮仍可交互。如果用户在这 3 秒里清空了 输入框或刷新了图片,下一次重试会用空的 GetCaptchaParameter() 发出请求, 而空答案会让服务端把本 session 的 4 位验证码换成 8 位。 在循环每次 POST 之前调用 CaptchaIsMissing()(它自己会提示并恢复按钮), 并用 Handled 标志让外层直接返回,不覆盖它设置的提示。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
contest.php 或 submit.php 的 fetch 被 reject(网络错误)时,异常会一路穿出 SubmitToEndedContestProblem、穿出 .then 回调、穿出 PassCheck 的 async 监听器 ——整条链上没有任何 catch。结果 ShowSubmitStatus 和恢复按钮的两行都不会执行, 提交按钮永远停在"正在提交...",而错误框在监听器开头已经被设成 display: none, 用户什么提示都看不到。这正是本 PR 声称要修掉的那个症状。 把两处网络请求都包进 try/catch,失败时返回错误信息交给外层显示。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ack-1017 fix: 比赛结束后回退提交不再被静默丢弃
Reviewer's GuideVersion 3.6.5 improves submission of problems from ended contests by extracting the fallback into a resilient, retrying workflow, centralizing status/error handling, and updating release metadata. Sequence diagram for ended-contest problem submissionsequenceDiagram
actor User
participant SubmitHandler
participant XMOJ as XMOJ
participant ContestPage
participant SubmitPage
User->>SubmitHandler: click PassCheck
SubmitHandler->>XMOJ: POST submit.php
XMOJ-->>SubmitHandler: 没有这个比赛!
SubmitHandler->>ContestPage: fetch contest.php?cid=ContestID
ContestPage-->>SubmitHandler: contest HTML
SubmitHandler->>SubmitHandler: parse RealPID
loop up to 5 attempts
SubmitHandler->>SubmitHandler: CaptchaIsMissing()
SubmitHandler->>SubmitPage: POST submit.php with RealPID
alt redirected
SubmitPage-->>SubmitHandler: redirect response
SubmitHandler->>XMOJ: navigate to result URL
else 请勿重复提交
SubmitPage-->>SubmitHandler: cooldown response
SubmitHandler->>SubmitHandler: wait 3 seconds
else submission result
SubmitPage-->>SubmitHandler: result HTML
end
end
SubmitHandler->>SubmitHandler: ShowSubmitStatus(Message)
Flow diagram for resilient ended-contest submission fallbackflowchart TD
A[Initial submission fails with 没有这个比赛] --> B[Fetch contest.php using cid]
B --> C{Contest page valid?}
C -- No --> D[Show failure status]
C -- Yes --> E[Parse contest problem list and resolve RealPID]
E --> F{RealPID found?}
F -- No --> D
F -- Yes --> G[Check captcha]
G --> H[POST submission to submit.php for RealPID]
H --> I{Response}
I -- Redirected --> J[Navigate to submission result]
I -- 验证码错误 --> K[RefreshCaptcha and show captcha error]
I -- 请勿重复提交 --> L{Attempts remain?}
L -- Yes --> M[Wait 3 seconds and retry]
M --> G
L -- No --> D
I -- Other failure --> D
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Deploying xmoj-script-dev-channel with
|
| Latest commit: |
fce1af6
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://ce2b43f8.xmoj-script-dev-channel.pages.dev |
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="XMOJ.user.js" line_range="4639" />
<code_context>
- SmartAlert("XMOJ-Script internal error!\n\n" + e + "\n\n" + "If you see this message, please report it to the developer.\nDon't forget to include console logs and a way to reproduce the error!\n\nDon't want to see this message? Disable DebugMode.");
+ let FailMessage = "提交失败!请关闭脚本后重试!";
+ if (text.indexOf("没有这个比赛!") !== -1 && SearchParams.get("pid") !== null) {
+ const FallbackResult = await SubmitToEndedContestProblem(CodeMirrorElement.getValue(), o2Switch, ShowSubmitStatus);
+ if (FallbackResult.Success || FallbackResult.Handled) {
+ return;
</code_context>
<issue_to_address>
**issue (bug_risk):** The fetch that submits the original contest request is still outside any try/catch. When this submit.php request rejects because of a network failure, the PassCheck async listener rejects before it can restore the submit button or show an error, so the button remains stuck on “正在提交...” with no visible message.
**Triggers:** When the initial contest submission request fails at the network level before returning a Response.
**Suggested fix:** Wrap the PassCheck submit fetch and response-processing chain in try/catch, and restore `Submit.disabled`/`Submit.value` while displaying a network-error message in the catch path.
</issue_to_address>Sourcery assessment
Needs a human reviewer. 1 finding to address first, and when the contest-to-problem mapping or retry logic is wrong, this code can POST the user's source to the wrong problem or create duplicate submissions, and those external submission records are not undone by reverting the script. The impact is bounded to the affected submissions and does not involve money or access control.
Blocking findings: XMOJ.user.js:4639
| SmartAlert("XMOJ-Script internal error!\n\n" + e + "\n\n" + "If you see this message, please report it to the developer.\nDon't forget to include console logs and a way to reproduce the error!\n\nDon't want to see this message? Disable DebugMode."); | ||
| let FailMessage = "提交失败!请关闭脚本后重试!"; | ||
| if (text.indexOf("没有这个比赛!") !== -1 && SearchParams.get("pid") !== null) { | ||
| const FallbackResult = await SubmitToEndedContestProblem(CodeMirrorElement.getValue(), o2Switch, ShowSubmitStatus); |
There was a problem hiding this comment.
issue (bug_risk): The fetch that submits the original contest request is still outside any try/catch. When this submit.php request rejects because of a network failure, the PassCheck async listener rejects before it can restore the submit button or show an error, so the button remains stuck on “正在提交...” with no visible message.
Triggers: When the initial contest submission request fails at the network level before returning a Response.
Suggested fix: Wrap the PassCheck submit fetch and response-processing chain in try/catch, and restore Submit.disabled/Submit.value while displaying a network-error message in the catch path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
feat: 验证码识别不出时自动换一张
Update to release 3.7.0
sync-branches: New code has just landed in dev, so let's bring extern-contrib up to speed!
Summary by Sourcery
Synchronize the external-contrib branch with dev by improving captcha recovery and making ended-contest fallback submissions reliable.
New Features:
Bug Fixes:
Enhancements:
Build:
Chores:
Summary by cubic
Syncs
extern-contribwithdev, delivering the 3.6.5 fallback-submission fix and the 3.6.6 captcha auto-refresh as release 3.7.0.XMOJ.user.jsandpackage.jsonare bumped to 3.7.0, andUpdate.jsonmarks 3.6.5 and 3.6.6 as prereleases with 3.7.0 as the release.Bug Fixes
请勿重复提交cooldowns (3 seconds apart, up to 5 attempts) instead of being silently dropped..jumbotronmessage, and captcha errors refresh the captcha and stop retrying.New Features
Written for commit fce1af6. Summary will update on new commits.