-
Notifications
You must be signed in to change notification settings - Fork 6
feat: 验证码识别不出时自动换一张 #1023
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: 验证码识别不出时自动换一张 #1023
Changes from all commits
ba08aac
c2b21da
05e1956
2544311
62e9c7f
abff304
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| // ==UserScript== | ||
| // @name XMOJ | ||
| // @version 3.6.5 | ||
| // @version 3.6.6 | ||
| // @description XMOJ增强脚本 | ||
| // @author @XMOJ-Script-dev, @langningchen and the community | ||
| // @namespace https://github/langningchen | ||
|
|
@@ -576,6 +576,8 @@ const CaptchaGlyphs = { | |
| // generated and 40 live captchas, 4 is the point where every wrong answer turns into a decline: it | ||
| // still fills in about three quarters of them and never once guessed wrong. | ||
| const CaptchaMinMargin = 4; | ||
| // With about three quarters of challenges read, five images leave well under a 1% chance of giving up. | ||
| const CaptchaMaxAttempts = 5; | ||
| // Settings that start off rather than on. Both UtilityEnabled and the settings list seed missing | ||
| // values, so they have to agree or whichever runs first decides the default. | ||
| const DefaultOffSettings = ["DebugMode", "SuperDebug", "ReplaceXM"]; | ||
|
|
@@ -4395,40 +4397,61 @@ async function main() { | |
| document.querySelector("#CaptchaElement").style.display = "block"; | ||
| CaptchaInput.value = ""; | ||
| SetCaptchaStatus(StatusMessage || ""); | ||
| let ImageBlob; | ||
| try { | ||
| const CaptchaResponse = await fetch("https://www.xmoj.tech/vcode.php?" + Math.random(), {cache: "no-store"}); | ||
| ImageBlob = await CaptchaResponse.blob(); | ||
| } catch (e) { | ||
| console.error(e); | ||
| SetCaptchaStatus("验证码加载失败,请点击图片重试"); | ||
| return; | ||
| } | ||
| if (RequestID !== CaptchaRequestID) return; | ||
| if (CaptchaObjectURL !== null) URL.revokeObjectURL(CaptchaObjectURL); | ||
| CaptchaObjectURL = URL.createObjectURL(ImageBlob); | ||
| document.querySelector("#CaptchaImage").src = CaptchaObjectURL; | ||
| if (!UtilityEnabled("AutoCaptcha")) return; | ||
| let CaptchaLength = 4; | ||
| try { | ||
| CaptchaLength = await GetCaptchaLength(ImageBlob); | ||
| } catch (e) { | ||
| console.error(e); | ||
| } | ||
| if (CaptchaLength !== 4) { | ||
| SetCaptchaStatus("本次为 " + CaptchaLength + " 位字母验证码,请手动输入"); | ||
| return; | ||
| } | ||
| const Answer = await SolveCaptcha(ImageBlob); | ||
| if (RequestID !== CaptchaRequestID) return; | ||
| if (Answer === null) { | ||
| SetCaptchaStatus("这张看不太准,请手动输入,或点击图片换一张"); | ||
| return; | ||
| // Only a submitted answer counts against the session, so fetching another image is | ||
| // free: when the solver declines one it is cheaper to ask for a fresh challenge than | ||
| // to make the user type it. Each fetch replaces the answer the session expects, so | ||
| // this stops if the user starts typing against the image on screen before the next one. | ||
| for (let Attempt = 1; Attempt <= CaptchaMaxAttempts; Attempt++) { | ||
| if (Attempt > 1) { | ||
| await new Promise((Resolve) => setTimeout(Resolve, 300)); | ||
| if (RequestID !== CaptchaRequestID || CaptchaInput.value !== "") return; | ||
| SetCaptchaStatus("这张看不太准,正在自动换一张(" + Attempt + "/" + CaptchaMaxAttempts + ")"); | ||
| } | ||
| // From the moment vcode.php is requested the image on screen no longer matches the | ||
| // session, so anything typed from it would be a guaranteed wrong answer. The box is | ||
| // locked until the new image replaces it. A newer call that takes over leaves the | ||
| // lock to be released by that call rather than by this one. | ||
| CaptchaInput.readOnly = true; | ||
| let ImageBlob; | ||
| try { | ||
| const CaptchaResponse = await fetch("https://www.xmoj.tech/vcode.php?" + Math.random(), {cache: "no-store"}); | ||
| ImageBlob = await CaptchaResponse.blob(); | ||
| } catch (e) { | ||
| console.error(e); | ||
| if (RequestID === CaptchaRequestID) { | ||
| CaptchaInput.readOnly = false; | ||
| SetCaptchaStatus("验证码加载失败,请点击图片重试"); | ||
| } | ||
| return; | ||
| } | ||
| if (RequestID !== CaptchaRequestID) return; | ||
| if (CaptchaObjectURL !== null) URL.revokeObjectURL(CaptchaObjectURL); | ||
| CaptchaObjectURL = URL.createObjectURL(ImageBlob); | ||
| document.querySelector("#CaptchaImage").src = CaptchaObjectURL; | ||
| CaptchaInput.value = ""; | ||
| CaptchaInput.readOnly = false; | ||
| if (!UtilityEnabled("AutoCaptcha")) return; | ||
| let CaptchaLength = 4; | ||
| try { | ||
| CaptchaLength = await GetCaptchaLength(ImageBlob); | ||
| } catch (e) { | ||
| console.error(e); | ||
| } | ||
| if (CaptchaLength !== 4) { | ||
| SetCaptchaStatus("本次为 " + CaptchaLength + " 位字母验证码,请手动输入"); | ||
| return; | ||
| } | ||
| const Answer = await SolveCaptcha(ImageBlob); | ||
| if (RequestID !== CaptchaRequestID) return; | ||
| // Never overwrite what the user has already started typing. | ||
| if (CaptchaInput.value !== "") return; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
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, Useful? React with 👍 / 👎. |
||
| if (Answer !== null) { | ||
| CaptchaInput.value = Answer; | ||
| SetCaptchaStatus("已自动识别,若与图片不符请手动修改"); | ||
| return; | ||
| } | ||
| } | ||
| // Never overwrite what the user has already started typing. | ||
| if (CaptchaInput.value !== "") return; | ||
| CaptchaInput.value = Answer; | ||
| SetCaptchaStatus("已自动识别,若与图片不符请手动修改"); | ||
| SetCaptchaStatus("连续几张都看不太准,请手动输入,或点击图片换一张"); | ||
| }; | ||
| document.querySelector("#CaptchaImage").addEventListener("click", () => { | ||
| RefreshCaptcha(""); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.