@@ -286,4 +286,49 @@ Status: new
286286Priority: -1
287287
288288Whether session/task reports should cite commit hashes for traceability
289- (undecided; currently reports cite task names and dates only).
289+ (undecided; currently reports cite task names and dates only).
290+
291+ ## Auto mode: HTML page detection + auto solve
292+
293+ Status: new
294+ Priority: -1
295+
296+ The library accepts the source code (HTML) of a page plus the page
297+ URL; it detects which captcha the page uses, extracts the needed
298+ tokens (sitekey / public_key / gt+challenge / captcha_id / ...) from
299+ the HTML, solves the captcha with a suitable provider, and returns an
300+ ` AutoSolveResult ` the caller can inject into the page's form inputs.
301+
302+ Design (ADR-0077):
303+ - New public module ` unicaptcha/detect.py ` : `detect(html, pageurl) ->
304+ tuple[ DetectedChallenge, ...] ` (DOM order; empty tuple when nothing
305+ found). ` DetectedChallenge{kind, challenge, page, signals} ` .
306+ - Stdlib-only parsing (` html.parser.HTMLParser ` + ` re ` + ` html.unescape ` )
307+ in ` _internal/_html.py ` ; no new runtime deps (ADR-0019).
308+ - Detectable kinds: reCAPTCHA v2 (incl. invisible), reCAPTCHA v3
309+ (render= / grecaptcha.execute), hCaptcha, Turnstile (incl. action /
310+ c_data / chl_page_data), FunCaptcha (data-pkey), GeeTest v3
311+ (initGeetest), GeeTest v4 (initGeetest4). Image/text excluded
312+ (API-driven, not HTML-detectable). v2 vs v3 disambiguated by
313+ render=/execute; both present -> two detections.
314+ - ` Solver.auto_solve ` / `AsyncSolver.auto_solve(html, pageurl,
315+ provider=None, * , index=0, time=None, retry=None, on_event=None) ->
316+ AutoSolveResult`: solves detected[ index] via the existing solve()
317+ path (ADR-0064 dispatch; provider= pins).
318+ - ` AutoSolveResult ` (frozen): ` result: TaskResult[BaseSolution] ` +
319+ ` fill: Mapping[str, str] ` — default selector->value per kind
320+ (#g-recaptcha-response, textarea[ name=h-captcha-response] ,
321+ input[ name=cf-turnstile-response] , #geetest_challenge/
322+ #geetest_validate/#geetest_seccode; GeeTest v4 field names verified
323+ during implementation; none for FunCaptcha). Caller applies to the
324+ live DOM (no browser).
325+ - New error ` NoCaptchaDetectedError(UnicaptchaError) ` on no detection.
326+ - pageurl is a required argument: serialized as websiteURL in the
327+ payload; the returned token is bound to that domain.
328+ - goals.md non-goal amended: HTML detection + auto solve in scope;
329+ browser automation stays out.
330+ - Tests: tests/test_detect.py (canned HTML per kind, multi-instance,
331+ v2/v3, malformed HTML), tests/test_auto_solve.py (respx end-to-end,
332+ uniform_choice monkeypatch, fill mapping).
333+
334+ References: ADR-0077.
0 commit comments