Skip to content

fix: 修复已结束比赛提交回退功能失效 #1017 - #1018

Open
INFP-coder wants to merge 39 commits into
XMOJ-Script-dev:extern-contribfrom
INFP-coder:master
Open

fix: 修复已结束比赛提交回退功能失效 #1017#1018
INFP-coder wants to merge 39 commits into
XMOJ-Script-dev:extern-contribfrom
INFP-coder:master

Conversation

@INFP-coder

@INFP-coder INFP-coder commented Aug 23, 2026

Copy link
Copy Markdown

新增回退提交后判断结果并阻断外层错误,外层处理会继续执行并覆盖为“提交失败”状态。

What does this PR aim to accomplish?:
修复已结束比赛的提交回退功能失效问题。当用户从已结束比赛的提交页(/submitpage.php?cid=&pid=)提交代码时,脚本原本应自动解析该比赛中的真实题目号,并向题目页面直接提交(回退),但此功能现已失效,导致用户显示“提交失败”且无任何回退记录。

本次 PR 旨在恢复此回退功能确保在各种比赛题目编号格式下均能正确解析真实 PID,同时优化错误处理,防止成功回退后被外层逻辑错误覆盖为“提交失败”。

How does this PR accomplish the above?:

改进真实题目号解析
原先依赖 substring(2, 6) 截取题号列,过于脆弱(当题号列为纯数字或格式变化时失败)。现改用 正则表达式 /\d+/ 从题号列文本中提取第一个数字,无论格式是“1”、“Problem 1”还是“问题 1”均可正确提取。

增加回退提交后的状态判断
回退提交后,检查响应是否发生重定向(Response.redirected),或响应文本中是否包含“提交成功”、“Solution”、“status.php”等成功标识。若成功,显示绿色成功提示,并 立即 return,阻止外层错误覆盖;若失败,显示具体错误信息并保留重试机会。

完善错误提示与用户体验
区分“回退中”、“回退成功”、“回退失败”三种状态,使用不同颜色(黄/绿/红)反馈,让用户清晰知晓当前进展。若解析真实 PID 失败,给出明确错误提示,引导用户手动提交。

错误检测范围扩展

除 “没有这个比赛!” 外,增加对 “比赛已结束” 等常见提示的检测(通过 text.indexOf 涵盖),但主要仍以 text.indexOf("没有这个比赛!") 作为回退触发点。


By submitting this pull request, I confirm the following:

  1. I have read and understood the contributor's guide, as well as this entire template. I understand which branch to base my commits and Pull Requests against.
  2. I have commented on my proposed changes within the code.
  3. I have tested my changes.
  4. I am willing to help maintain this change if there are issues with it later.
  5. It is compatible with the GNU General Public License v3.0
  6. I have squashed any insignificant commits. (git rebase)
  7. I have checked that another pull request for this purpose does not exist.
  8. I have considered and confirmed that this submission will be valuable to others.
  9. I accept that this submission may not be used, and the pull request can be closed at the will of the maintainer.
  10. I give this submission freely and claim no ownership to its content.
  11. I have verified that my changes work correctly in both the new UI and the old/classic UI.

  • I have read the above and my PR is ready for review. Check this box to confirm
    Testing:
  1. Go to a finished contest submit page (e.g., /submitpage.php?cid=123&pid=0).
  2. Enter any code and click "Submit".
  3. Observe that the fallback triggers and results in a success/failure message appropriate to the actual state.
    Fixed Screenshot:
image

Summary by Sourcery

恢复已结束比赛的提交回退流程并改进其结果处理与用户反馈。

Bug Fixes:

  • 修复已结束比赛提交页无法回退到真实题目提交的问题。
  • 修复回退提交成功后被外层逻辑误判为提交失败的问题。
  • 增强比赛题目编号解析及回退失败时的错误提示,支持用户重试或改为手动提交。

Enhancements:

  • 优化提交过程中的状态反馈,区分回退进行中、成功和失败状态。

Chores:

  • 更新版本元数据并新增 ads.txt,清理首页多余空行。

Summary by cubic

修复已结束比赛的提交回退被误判为失败。旧行为:题号解析脆弱且回退成功会被外层覆盖为失败;新行为:仅以服务端重定向判定成功,命中后立即短路并提示。

  • 触发:响应含“没有这个比赛!”或“比赛已结束”,且 URL 含 pid 时回退;初次提交若已重定向则直接跳转。
  • 解析:从比赛页题目列表第二列用正则提取首个数字,兼容“1”“Problem 1”等;无法获取或解析时提示并复位按钮。
  • 回退提交:向真实题目 POST;若重定向视为成功并跳转;否则提取 .jumbotron 或纯文本前 100 字作为错误信息,允许重试。
  • 交互:区分“回退中/成功/失败”(橙/绿/红),成功后禁用提交按钮;阻断外层错误覆盖。
  • 其他:更新版本元数据;新增 ads.txt;清理 index.html 多余空行。

Written for commit 9f07ee2. Summary will update on new commits.

Review in cubic

boomzero and others added 30 commits February 8, 2025 09:15
Signed-off-by: Zhu Chenrui <boomzero_zcr@outlook.com>
Signed-off-by: Zhu Chenrui <boomzero_zcr@outlook.com>
(cherry picked from commit 07d7590)

Update feature.yml

Signed-off-by: Zhu Chenrui <boomzero_zcr@outlook.com>
(cherry picked from commit 1a99430)

Update docs.yml

Signed-off-by: Zhu Chenrui <boomzero_zcr@outlook.com>
(cherry picked from commit 6017bcf)
Signed-off-by: Shan Wenxiao <seanoj_noreply@yeah.net>
…ns[bot]

This prevents infinite loops where the bot commits version updates,
which triggers the workflow again, causing another commit.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The last-commit-author guard now only exits for non-edited events,
so PR title/body changes still update Update.json metadata even
when the branch tip is a github-actions[bot] commit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Exclude all bot actors (not just github-actions[bot]) from triggering
the UpdateVersion workflow, preventing loops from AI code review bots.
Allow edited events through the script-level guard so PR title/body
changes still update Update.json metadata.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Shan Wenxiao <seanoj_noreply@yeah.net>
Removed Google Ads script from the HTML file.

Signed-off-by: Shan Wenxiao <seanoj_noreply@yeah.net>
Signed-off-by: Shan Wenxiao <seanoj_noreply@yeah.net>
boomzero and others added 2 commits July 27, 2026 13:42
新增回退提交后判断结果并阻断外层错误,外层处理会继续执行并覆盖为“提交失败”状态。

Signed-off-by: Feng Jiajun <kp6phnt44s@privaterelay.appleid.com>
@sourcery-ai

sourcery-ai Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Restores and hardens the fallback submission mechanism for finished contests by making problem ID parsing more robust, improving error handling and user feedback, and short‑circuiting outer error logic when the fallback submission succeeds or fails explicitly.

Flow diagram for robust contest problem ID resolution

flowchart TD
    A[Finished contest submission fails] --> B{Contest error detected?}
    B -- No --> C[Continue normal failure handling]
    B -- Yes --> D[Fetch contest page]
    D --> E{Contest page available?}
    E -- No --> F[Show contest information error]
    E -- Yes --> G[Read problem row number]
    G --> H[Extract first numeric sequence with /\\d+/]
    H --> I{Real PID resolved?}
    I -- No --> J[Show PID parsing error]
    I -- Yes --> K[POST code to submit.php with real PID]
Loading

File-Level Changes

Change Details Files
Improve contest problem ID extraction to be robust against varying problem number formats.
  • Extract contest ID and problem index from current URL once and reuse them.
  • Parse the contest page HTML and iterate the problem table rows to build a list of problem IDs.
  • Replace brittle substring-based ID parsing with a regex that pulls the first numeric token from the problem number cell text.
  • Short‑circuit with a user-facing error if a valid real problem ID cannot be resolved for the requested index.
XMOJ.user.js
Rework fallback submission flow for ended contests to provide clear success/failure states and prevent outer logic from overwriting a successful fallback.
  • Add user-visible error messages when the contest page cannot be fetched or is inaccessible, and re-enable the submit button in that case.
  • Show a yellow "contest ended, retrying" message before performing the fallback submission to the resolved problem ID.
  • Perform the fallback submission via a single awaited fetch, then inspect redirect and response text to determine success based on multiple markers.
  • On success, show a green success message, disable the submit button, and exit early; on failure, show a red failure message with a response preview, re-enable submission, and exit early instead of falling through to a generic failure state.
XMOJ.user.js

Possibly linked issues

  • #[Bug] 已结束比赛的直接题目提交回退功能失效: The PR restores ended-contest fallback submissions by robustly resolving real PIDs and preventing successful retries from being marked failed.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="XMOJ.user.js" line_range="4273-4275" />
<code_context>
+                                return;
+                            } else {
+                                const retryText = await retryResp.text();
+                                if (retryText.indexOf("提交成功") !== -1 || 
+                                    retryText.indexOf("Solution") !== -1 || 
+                                    retryText.indexOf("status.php") !== -1) {
+                                ErrorMessage.style.color = "green";
+                                ErrorMessage.innerText = "✅ 回退提交成功!请查看状态。";
</code_context>
<issue_to_address>
**issue (bug_risk):** The fallback treats any non-redirect response containing `status.php` as a successful submission, even when the response is an error page that includes the site's normal status-page navigation link. A failed fallback therefore displays “回退提交成功” and disables further submission attempts.

**Triggers:** When `submit.php` returns an HTML failure page without a redirect.

**Suggested fix:** Require a specific success response or successful submission status, and check `retryResp.ok` before reporting success instead of matching the generic `status.php` string.

```suggestion
                                if (retryResp.ok && (retryText.indexOf("提交成功") !== -1 || 
                                    retryText.indexOf("Solution") !== -1)) {
```
</issue_to_address>

### Comment 2
<location path="XMOJ.user.js" line_range="4218" />
<code_context>
                             } else {
                                 const text = await Response.text();
                                 if (text.indexOf("没有这个比赛!") !== -1 && new URL(location.href).searchParams.get("pid") !== null) {
-                                    // Credit: https://github.com/boomzero/quicksubmit/blob/main/index.ts
-                                    // Also licensed under GPL-3.0
</code_context>
<issue_to_address>
**issue (bug_risk):** Fallback is still triggered only when the original response contains the exact string `没有这个比赛!`; responses containing the newly described `比赛已结束` message, or another equivalent finished-contest message, bypass the fallback and are reported as ordinary submission failures.

**Triggers:** When the server reports a finished contest using `比赛已结束` without also including `没有这个比赛!`.

**Suggested fix:** Detect the complete set of finished/non-submit-able contest messages, including `比赛已结束`, before entering the fallback path.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 2 findings to address first, and if the contest-page parsing selects the wrong problem ID or the success detection is mistaken, the script can submit the user's code to an unintended problem and leave a persistent submission record that reverting cannot remove. The impact is bounded to the affected submission, but it is not fully reversible.

Blocking findings: XMOJ.user.js:4275, XMOJ.user.js:4218


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread XMOJ.user.js Outdated
Comment thread XMOJ.user.js Outdated
@@ -4216,78 +4216,77 @@ async function main() {
} else {
const text = await Response.text();
if (text.indexOf("没有这个比赛!") !== -1 && new URL(location.href).searchParams.get("pid") !== null) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Fallback is still triggered only when the original response contains the exact string 没有这个比赛!; responses containing the newly described 比赛已结束 message, or another equivalent finished-contest message, bypass the fallback and are reported as ordinary submission failures.

Triggers: When the server reports a finished contest using 比赛已结束 without also including 没有这个比赛!.

Suggested fix: Detect the complete set of finished/non-submit-able contest messages, including 比赛已结束, before entering the fallback path.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread XMOJ.user.js Outdated
style: 修复 DeepScan 格式问题

Signed-off-by: Feng Jiajun <kp6phnt44s@privaterelay.appleid.com>
Signed-off-by: Feng Jiajun <kp6phnt44s@privaterelay.appleid.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread XMOJ.user.js Outdated

@boomzero boomzero left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢你的第一个 PR!诊断方向是对的——核心问题确实是回退提交后没有 return,导致外层无条件覆盖成"提交失败"。另外用正则提取题号也比原来的 substring(2, 6) 更稳:原写法遇到 5 位题号会截断(186501865),会静默提交到错题,这个改进很有价值。

有几点需要处理。

1. 目标分支

外部贡献者的 PR 需要基于并指向 extern-contrib,不能直接指向 master。这是流程要求,和代码质量无关。

2. 阻塞项:成功判定会误报

if (retryText.indexOf("提交成功") !== -1 ||
    retryText.indexOf("Solution")   !== -1 ||
    retryText.indexOf("status.php") !== -1) {

status.php 出现在每个页面的导航栏里:

<li ><a href="status.php">状态</a></li>

而真正提交成功时 submit.php 会 302 到 status.php,在上面的 if (retryResp.redirected) 分支就已经 return 了。也就是说这段 else 只有在失败时才会走到,而它必定命中 status.php —— 结果是每次失败都会显示 "✅ 回退提交成功!请查看状态。" 并把按钮置成"已提交"。这比原来的通用报错更糟,用户会以为代码已经交上去了。

建议只把 redirected 当成功信号,其余一律按失败处理,并从响应的 .jumbotron 里取服务端的真实提示显示给用户。

3. #1017 里"没有提交记录"的真正原因

这部分从 issue 里看不出来,我补充一下。XMOJ 基于 HUSTOJ,trunk/web/submit.php 里有一段提交冷却:

if (!isset($OJ_SUBMIT_COOLDOWN_TIME)) $OJ_SUBMIT_COOLDOWN_TIME = 5;
$time_point = date("Y-m-d H:i:s", time() - $OJ_SUBMIT_COOLDOWN_TIME);
$sql = "SELECT `in_date`,solution_id FROM `solution` WHERE `user_id`=? AND in_date>? ORDER BY `in_date` DESC LIMIT 1";

上游命中时是 302,但 XMOJ 改成了直接渲染页面,.jumbotron 里是 请勿重复提交。issue 附的日志里,回退提交拿到的正是这个页面——所以 Response.redirected 是 false,响应体被丢掉,最终没有产生任何提交记录。

顺序上比赛校验(没有这个比赛!)在冷却检查之前,所以第一次 cid+pid 的失败提交本身不会写 solution 表,冷却是被用户前一次提交触发的。

要真正修好 #1017,回退提交遇到 请勿重复提交 时需要等冷却过去再重试(比如 3 秒一次、最多 5 次),期间在 ErrorMessage 里提示进度。

4. 一些小问题

  • 删掉了 quicksubmit 的 // Credit: 注释,那是 GPL-3.0 的署名要求,需要保留
  • 删掉了所有 _xmoj_disposeErrorMessageEditors() 调用,它负责在覆盖 innerText 前销毁错误框里的 Monaco 编辑器和 model,去掉会泄漏
  • retryText.substring(0, 200) 会把 <!DOCTYPE html>... 原样显示给用户,建议换成解析出来的服务端提示
  • 进行中的提示用了 yellow,浅色主题下白底黄字看不清(原来用的是 red)
  • 缩进被打乱成了 4/8/36 空格混排,麻烦按原文件风格调回来

第 1、2 点处理掉就可以合了。第 3 点的冷却重试如果你不想写,我也可以补一个 commit 上去。再次感谢!


这条 review 是 LLM 帮我整理的,我不想手写这么长的东西。有说得不对的地方直接指出来。

@boomzero

Copy link
Copy Markdown
Member

补充更正:上面第 1 点我最初写成了 dev,已改。外部贡献者的 PR 应该指向 extern-contrib——如果你已经照 dev 改了,改成 extern-contrib 就行,其余部分不受影响。

@INFP-coder

Copy link
Copy Markdown
Author

Problems List:
image

@INFP-coder
INFP-coder changed the base branch from master to extern-contrib August 23, 2026 02:07
@boomzero

Copy link
Copy Markdown
Member

HUSTOJ 对提交有 5s 的 rate limit

@INFP-coder

Copy link
Copy Markdown
Author

cnm点错了

@INFP-coder

Copy link
Copy Markdown
Author

算了先不squash了

Signed-off-by: Feng Jiajun <kp6phnt44s@privaterelay.appleid.com>
Signed-off-by: Feng Jiajun <kp6phnt44s@privaterelay.appleid.com>
@INFP-coder

Copy link
Copy Markdown
Author

本次修改仅限于 PassCheck 监听器。

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="XMOJ.user.js">

<violation number="1" location="XMOJ.user.js:4237">
P2: When the server reports a finished contest with `比赛已结束` or equivalent wording, this exact-match guard skips rollback. Match the supported finished-contest phrases before falling through to generic failure handling.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread XMOJ.user.js Outdated
Comment thread XMOJ.user.js Outdated
const text = await response.text();

// 回退处理:比赛已结束,尝试直接提交到真实题目
if (text.indexOf("没有这个比赛!") !== -1 && new URL(location.href).searchParams.get("pid") !== null) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When the server reports a finished contest with 比赛已结束 or equivalent wording, this exact-match guard skips rollback. Match the supported finished-contest phrases before falling through to generic failure handling.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At XMOJ.user.js, line 4237:

<comment>When the server reports a finished contest with `比赛已结束` or equivalent wording, this exact-match guard skips rollback. Match the supported finished-contest phrases before falling through to generic failure handling.</comment>

<file context>
@@ -4211,116 +4211,127 @@ async function main() {
+    const text = await response.text();
+
+    // 回退处理:比赛已结束,尝试直接提交到真实题目
+    if (text.indexOf("没有这个比赛!") !== -1 && new URL(location.href).searchParams.get("pid") !== null) {
+        // Credit: https://github.com/boomzero/quicksubmit/blob/main/index.ts (GPL-3.0)
+        const cid = new URL(location.href).searchParams.get("cid");
</file context>
Suggested change
if (text.indexOf("没有这个比赛!") !== -1 && new URL(location.href).searchParams.get("pid") !== null) {
if ((text.indexOf("没有这个比赛!") !== -1 || text.indexOf("比赛已结束") !== -1 || text.indexOf("比赛已经结束") !== -1) && new URL(location.href).searchParams.get("pid") !== null) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复 请重新审查。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@INFP-coder I have started the AI code review. It will take a few minutes to complete.

Signed-off-by: Feng Jiajun <kp6phnt44s@privaterelay.appleid.com>
@boomzero

boomzero commented Aug 23, 2026

Copy link
Copy Markdown
Member

分支和那几个小的都改好了,.jumbotron 那段也写对了。但成功判定还是原样:

if (retryText.indexOf("提交成功") !== -1 ||
    retryText.indexOf("Solution") !== -1 ||
    retryText.indexOf("status.php") !== -1) {

留着这条,你新写的 jumbotron 提取分支永远走不到。每个页面导航栏都有 <li ><a href="status.php">状态</a></li>,失败页同样有——#1017 日志里那个 请勿重复提交 的页面就带这行,会被判成成功,弹 "✅ 回退提交成功!请查看状态。" 再把按钮锁成"已提交"。

真提交成功是 302,上面 retryResp.redirected 已经 return 了,所以这个 else 只有失败才会进来。整个 if 删掉、直接走下面那段 jumbotron 提取就对了。

另外冷却重试还没加。#1017 里"状态里没有提交记录"就是它引起的,不加的话原来的现象还在,只是从"提交失败"变成误报"提交成功"。要我补一个 commit 上去吗?


同上,LLM 帮我整理的。

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="XMOJ.user.js">

<violation number="1" location="XMOJ.user.js:4237">
P3: The entire new block is indented at 4 spaces while the surrounding code of the PassCheck `click` handler is nested at 24 spaces. This drops the added code out of the visual nesting level, making the handler body read as if it were separate top-level code and hurting maintainability. The repo convention is to preserve original formatting (CLAUDE.md: "Do NOT run code formatters - maintain original formatting"). Re-indent the block to match the surrounding level.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread Update.json
Comment thread XMOJ.user.js Outdated
Comment thread XMOJ.user.js
const text = await response.text();

// 回退处理:比赛已结束或不存在,尝试直接提交到真实题目
if ((text.indexOf("没有这个比赛!") !== -1 || text.indexOf("比赛已结束") !== -1) && new URL(location.href).searchParams.get("pid") !== null) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The entire new block is indented at 4 spaces while the surrounding code of the PassCheck click handler is nested at 24 spaces. This drops the added code out of the visual nesting level, making the handler body read as if it were separate top-level code and hurting maintainability. The repo convention is to preserve original formatting (CLAUDE.md: "Do NOT run code formatters - maintain original formatting"). Re-indent the block to match the surrounding level.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At XMOJ.user.js, line 4237:

<comment>The entire new block is indented at 4 spaces while the surrounding code of the PassCheck `click` handler is nested at 24 spaces. This drops the added code out of the visual nesting level, making the handler body read as if it were separate top-level code and hurting maintainability. The repo convention is to preserve original formatting (CLAUDE.md: "Do NOT run code formatters - maintain original formatting"). Re-indent the block to match the surrounding level.</comment>

<file context>
@@ -4211,98 +4211,143 @@ async function main() {
+    const text = await response.text();
+
+    // 回退处理:比赛已结束或不存在,尝试直接提交到真实题目
+if ((text.indexOf("没有这个比赛!") !== -1 || text.indexOf("比赛已结束") !== -1) && new URL(location.href).searchParams.get("pid") !== null) {
+    // Credit: https://github.com/boomzero/quicksubmit/blob/main/index.ts (GPL-3.0)
+    const cid = new URL(location.href).searchParams.get("cid");
</file context>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 existing issue remains and 1 new issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="XMOJ.user.js">

<violation number="1" location="XMOJ.user.js:4312">
P2: After a non-redirected fallback submission succeeds, `PassCheck` remains visible and clickable, so users can submit the same code repeatedly despite the success state. Hide or disable `PassCheck` when marking the fallback submission successful.</violation>
</file>

Requires human review: Auto-approval blocked because this review re-detected 3 unresolved issues already reported by Cubic.

Re-trigger cubic

Comment thread XMOJ.user.js Outdated
ErrorElement.style.display = "block";
ErrorMessage.style.color = "green";
ErrorMessage.innerText = "✅ 回退提交成功!请查看状态。";
Submit.disabled = true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: After a non-redirected fallback submission succeeds, PassCheck remains visible and clickable, so users can submit the same code repeatedly despite the success state. Hide or disable PassCheck when marking the fallback submission successful.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At XMOJ.user.js, line 4312:

<comment>After a non-redirected fallback submission succeeds, `PassCheck` remains visible and clickable, so users can submit the same code repeatedly despite the success state. Hide or disable `PassCheck` when marking the fallback submission successful.</comment>

<file context>
@@ -4211,98 +4211,143 @@ async function main() {
+            ErrorElement.style.display = "block";
+            ErrorMessage.style.color = "green";
+            ErrorMessage.innerText = "✅ 回退提交成功!请查看状态。";
+            Submit.disabled = true;
+            Submit.value = "已提交";
+            return;
</file context>
Suggested change
Submit.disabled = true;
Submit.disabled = true;
PassCheck.style.display = "none";

Signed-off-by: Feng Jiajun <kp6phnt44s@privaterelay.appleid.com>
@boomzero

boomzero commented Aug 23, 2026

Copy link
Copy Markdown
Member

成功判定改对了,redirected 之外一律按失败走 .jumbotron,这样就行了。

不过现在这版有个更要命的问题:文件语法都过不了,整个脚本会加载失败。

$ node --check XMOJ.user.js
XMOJ.user.js:4329
}
^
SyntaxError: missing ) after argument list

4327–4329 连着三个 },多了一个。把 4329 那个删掉就能过了(我试过,删掉之后 node --check 就干净了)。

顺手再提几个:

  • 4297/4298 两行 // 检查是否提交成功(重定向 或 响应含成功标记) 重复了
  • 代码里留了几条像是编辑指令的注释,提交前记得删:// ❌ 删除这里的成功关键词判断 —— 进入 else 就是失败// ✅ 直接从响应中提取错误信息}); // ← 这是唯一正确的结束
  • 缩进还是乱的,if (retryResp.redirected) 顶到第 0 列了,跟周围对不上
  • PR 里除了 XMOJ.user.js 还带上了 ads.txtindex.htmlUpdate.json,应该是之前把 extern-contrib 合进 master 带进来的,最好清掉只留脚本改动

冷却重试还是没加,所以 #1017 的现象目前还在——只是从误报"提交成功"变成了如实显示"❌ 回退提交失败:请勿重复提交"。这一步比之前对,但功能还没通。要我补一个 commit 上去吗?

推之前跑一下 node --check XMOJ.user.js 就能挡掉这类问题。


同上,LLM 帮我整理的。

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="XMOJ.user.js">

<violation number="1" location="XMOJ.user.js:4316">
P0: The extra closing brace makes `XMOJ.user.js` syntactically invalid, so the userscript cannot load at all. Remove the obsolete brace left behind by deleting the nested success check.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread XMOJ.user.js
} else {
const textOnly = retryText.replace(/<[^>]*>/g, "").trim();
errorMsg = textOnly.substring(0, 100) || errorMsg;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0: The extra closing brace makes XMOJ.user.js syntactically invalid, so the userscript cannot load at all. Remove the obsolete brace left behind by deleting the nested success check.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At XMOJ.user.js, line 4316:

<comment>The extra closing brace makes `XMOJ.user.js` syntactically invalid, so the userscript cannot load at all. Remove the obsolete brace left behind by deleting the nested success check.</comment>

<file context>
@@ -4295,45 +4295,35 @@ if ((text.indexOf("没有这个比赛!") !== -1 || text.indexOf("比赛已结
-            return;
+            const textOnly = retryText.replace(/<[^>]*>/g, "").trim();
+            errorMsg = textOnly.substring(0, 100) || errorMsg;
+        }
+    } catch (_) {
+        // 解析失败则使用默认信息
</file context>

@boomzero

boomzero commented Aug 23, 2026

Copy link
Copy Markdown
Member

extern-contrib 刚合了 #1019 / #1020,这个 PR 现在是 CONFLICTING,需要把 extern-contrib 合回来重新解一次。

冲突正好落在你改的那个 PassCheck 监听器上。解的时候有两处别丢掉:

1. 处理器开头新增的验证码检查

PassCheck.addEventListener("click", async () => {
    if (CaptchaIsMissing()) return;
    ...

2. 回退提交的 body 要接上 GetCaptchaParameter()

extern-contrib 上现在是这样的:

"body": "id=" + rPID + "&language=1&" + "source=" + encodeURIComponent(CodeMirrorElement.getValue()) + o2Switch + GetCaptchaParameter()

你这版回退提交没带 vcode。评测队列忙、验证码出来的时候,回退提交会因为缺 vcode 直接失败——而且按 #1019 注释里的说法,空答案会让服务端把这个 session 的 4 位验证码换成 8 位,代价不小。

另外前面那个语法错误(4329 行多的 })还没修,cubic 也标了同一个 P0。冷却重试也还没加。


同上,LLM 帮我整理的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants