Skip to content

feat: 验证码识别不出时自动换一张 - #1023

Merged
boomzero merged 6 commits into
devfrom
feat/captcha-auto-retry
Sep 19, 2026
Merged

boomzero merged 6 commits into
devfrom
feat/captcha-auto-retry

Conversation

@boomzero

@boomzero boomzero commented Sep 19, 2026

Copy link
Copy Markdown
Member

What does this PR aim to accomplish?:

When AutoCaptcha declines a 4-digit captcha (too close to call), the user currently has to type it or click the image for a new one. This PR makes the script fetch a new challenge automatically instead.

How does this PR accomplish the above?:

  • RefreshCaptcha now loops up to CaptchaMaxAttempts (5) times, waiting 300ms between fetches, while the solver keeps returning null. The status line shows progress (正在自动换一张(2/5)) and falls back to asking for manual input if all of them fail.
  • Fetching vcode.php does not count as a failed attempt (only a submitted blank/wrong answer escalates to the 8-char challenge), so retries are safe.
  • The loop stops as soon as the user starts typing (a new fetch would invalidate the image they're reading), when the image is clicked (the CaptchaRequestID check), on 8-character challenges, and on network errors.
  • The submit error paths that await RefreshCaptcha may now take up to ~1–2s longer in the worst case.

⚠️ Not yet tested in a browser: only node --check was run. Items 3 and 11 need human verification (new UI and classic UI).


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.
  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.
  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 PR 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.

🤖 Generated with Claude Code

Summary by Sourcery

Automatically replace ambiguous captchas during recognition so users can retry without manually changing the image.

New Features:

  • Automatically fetch replacement 4-digit captchas when AutoCaptcha cannot confidently recognize the current image, retrying up to five times before requesting manual input.

Bug Fixes:

  • Prevent captcha refresh retries from escalating the session to the harder challenge and preserve user-entered answers or newer captcha requests.

Enhancements:

  • Stop automatic retries on user interaction, unsupported captcha lengths, and network failures while providing progress and fallback status messages.

Build:

  • Bump the userscript and package versions to 3.6.6 and update release metadata.

Summary by cubic

AutoCaptcha now fetches a replacement captcha automatically when it can't read the current one, instead of asking the user to type it or click the image. The captcha input is locked while a replacement loads so a stale image can't be answered. Bumps XMOJ.user.js, Update.json, and package.json to 3.6.6.

  • Retries up to 5 times with 300ms between attempts, then falls back to manual input.
  • Fetching a replacement doesn't count as an incorrect answer, so retries won't trigger the harder 8-character challenge.
  • Retries stop on manual input, image clicks, non-4-digit captchas, or fetch failures.
  • Only node --check has been run; both new and classic UIs still need browser verification.

Written for commit abff304. Summary will update on new commits.

Review in cubic

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Updates captcha refresh handling to automatically try up to five newly fetched images when AutoCaptcha cannot confidently recognize a 4-digit challenge, while guarding against stale requests, user interaction, unsupported challenge lengths, and network failures before falling back to manual entry.

Sequence diagram for automatic captcha retry

sequenceDiagram
    participant User
    participant RefreshCaptcha
    participant CaptchaServer
    participant SolveCaptcha
    participant CaptchaInput

    RefreshCaptcha->>CaptchaServer: fetch(vcode.php)
    CaptchaServer-->>RefreshCaptcha: ImageBlob
    RefreshCaptcha->>SolveCaptcha: SolveCaptcha(ImageBlob)
    SolveCaptcha-->>RefreshCaptcha: null
    loop up to CaptchaMaxAttempts (5)
        RefreshCaptcha->>RefreshCaptcha: wait 300ms
        RefreshCaptcha->>CaptchaServer: fetch(vcode.php)
        CaptchaServer-->>RefreshCaptcha: ImageBlob
        RefreshCaptcha->>SolveCaptcha: SolveCaptcha(ImageBlob)
        SolveCaptcha-->>RefreshCaptcha: answer or null
    end
    alt answer recognized
        RefreshCaptcha->>CaptchaInput: set value
    else user starts typing or clicks image
        RefreshCaptcha-->>User: stop retrying
    else all attempts declined
        RefreshCaptcha-->>User: request manual input
    end
Loading

File-Level Changes

Change Details Files
Retry declined 4-digit captcha recognition by fetching fresh challenges automatically.
  • Added a five-attempt retry limit with 300 ms delays and progress status updates.
  • Stopped retries on user input, image refresh/click, non-4-digit challenges, stale requests, and network errors.
  • Added manual-input fallback after all attempts are declined.
XMOJ.user.js
Preserved captcha session safety while cycling images.
  • Treated image fetches as non-submitting operations so they do not escalate the challenge.
  • Replaced object URLs and updated the displayed image for each attempt.
  • Avoided overwriting user-entered captcha text and retained existing successful auto-fill behavior.
XMOJ.user.js

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

@hendragon-bot hendragon-bot Bot added the user-script This issue or pull request is related to the main user script label Sep 19, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 19, 2026

Copy link
Copy Markdown

Deploying xmoj-script-dev-channel with  Cloudflare Pages  Cloudflare Pages

Latest commit: abff304
Status:⚡️  Build in progress...

View logs

@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 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="4419-4420" />
<code_context>
+                                const CaptchaResponse = await fetch("https://www.xmoj.tech/vcode.php?" + Math.random(), {cache: "no-store"});
</code_context>
<issue_to_address>
**issue (bug_risk):** When the user starts typing while a captcha fetch is in progress, the completed fetch still revokes the displayed image and replaces it before checking `CaptchaInput.value`. The typed answer therefore targets the old image while the session expects the newly fetched challenge.

**Triggers:** When the user begins entering an answer before `fetch(...).blob()` resolves.

**Suggested fix:** Check `CaptchaInput.value` again immediately after the blob fetch and before revoking `CaptchaObjectURL` or assigning `CaptchaImage.src`.

```suggestion
                            if (RequestID !== CaptchaRequestID) return;
                            if (CaptchaInput.value !== "") return;
                            if (CaptchaObjectURL !== null) URL.revokeObjectURL(CaptchaObjectURL);
```
</issue_to_address>

Sourcery assessment

Approval pending. 1 finding to address first.

Blocking findings: XMOJ.user.js:4420


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread XMOJ.user.js

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ba08aac5b1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread XMOJ.user.js
const Answer = await SolveCaptcha(ImageBlob);
if (RequestID !== CaptchaRequestID) return;
// Never overwrite what the user has already started typing.
if (CaptchaInput.value !== "") return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Prevent typing while a retry replaces the challenge

When a user starts manually entering the currently displayed captcha after the pre-fetch check on line 4407 but before the retry fetch and solver finish, vcode.php has already replaced the session's expected answer and the image is replaced on line 4422. This late check then returns while preserving the answer typed from the old image, so the next submission is guaranteed to fail and may escalate the session to the harder captcha. Disable manual entry during an in-flight automatic refresh or otherwise clear/reconcile input when the fetched challenge replaces the displayed one.

Useful? React with 👍 / 👎.

@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.

Sourcery assessment

Approved.

@boomzero

Copy link
Copy Markdown
Member Author

Tested and works

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pull-request-size pull-request-size Bot added size/L and removed size/M labels Sep 19, 2026
@boomzero
boomzero merged commit 5f348ff into dev Sep 19, 2026
4 of 6 checks passed
@boomzero
boomzero deleted the feat/captcha-auto-retry branch September 19, 2026 00:56
@boomzero boomzero mentioned this pull request Sep 19, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L user-script This issue or pull request is related to the main user script

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant