The two Tradeify automations clicked the 2captcha *extension's* solve button and waited for it to go green. That needed a second extension installed and signed in, put a real mouse click on a button whose markup is 2captcha's to change, and gave a run no way to tell "still solving" from "not installed". Replaced with one `solveCaptcha` step. No mouse: the extension reads the widget's sitekey out of the page, the dashboard buys a token from 2captcha, and the extension puts it in the response field and fires the page's own callback. captcha-hook.js is the part that earns its keep. A widget rendered programmatically puts nothing in the DOM — no sitekey, and no callback. Most pages only enable submit from that callback, so filling the hidden field alone leaves the page looking unsolved. The hook wraps turnstile/grecaptcha/hcaptcha `render` at document_start to hold on to what the page passed. Solves go through 2captcha's residential proxy. Its API rejects host names in proxyAddress, so na.proxy.2captcha.com is resolved to an IP first (cached); the gateway was confirmed to work addressed that way. Covers reCAPTCHA v2 (incl. invisible and Enterprise), hCaptcha and Turnstile. NOT reCAPTCHA v3: a v3 page carries an anchor iframe with k=, so it is detected as v2 and would be solved with the wrong task type. Everything else unsupported fails loudly instead. The API key and proxy credentials are hardcoded in the captcha route on request. Unlike the sqlite database, that file is in the repo, so they travel with it. TWOCAPTCHA_API_KEY / TWOCAPTCHA_PROXY and the settings rows still override; neither has a field on the Settings page. Runner VERSION and RUNNER_EXPECTED_VERSION both to 0.17.0 — they are a pair, and a mismatch shows as a red "restart your runner" banner that blames the wrong process. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
71 lines
3.4 KiB
Markdown
71 lines
3.4 KiB
Markdown
# AutoFirmer Capture (Chromium extension)
|
|
|
|
Scrapes the firm tab you are looking at and posts its HTML back to the
|
|
dashboard. There is no on/off switch for that — see **Scope** below for what
|
|
limits it instead.
|
|
|
|
## Install (unpacked)
|
|
|
|
1. Start the dashboard (`npm run dev`) so `http://localhost:3000` is up.
|
|
2. Open `chrome://extensions`, enable **Developer mode** (top right).
|
|
3. **Load unpacked** → select this `extension/` folder.
|
|
4. Click the extension icon to open the popup and set:
|
|
- **Dashboard URL** — default `http://localhost:3000`. Use the VPS IP if the
|
|
dashboard runs elsewhere.
|
|
- **Poll interval** — seconds between status checks (default 3).
|
|
- **Element selector** — optional CSS selector; matching elements get their
|
|
on-screen position measured alongside the HTML.
|
|
|
|
The badge shows `!` (red) if the dashboard is unreachable, and nothing otherwise
|
|
— blank is the working state. Open the popup for what the last tick actually did.
|
|
|
|
## Flow
|
|
|
|
```
|
|
extension --GET /api/autobuyer/status--> { pendingLocate }
|
|
extension --POST /api/autobuyer/capture-> html + viewport + element rects
|
|
AutoBuyer page --GET /api/autobuyer/capture-> renders the HTML
|
|
```
|
|
|
|
Nothing in that loop is switchable. Every tick serves any queued clicks and then
|
|
captures the tab you are on.
|
|
|
|
## Scope
|
|
|
|
Capture has no switch, so scope is what keeps it honest. Three limits, all
|
|
enforced by Chrome rather than by this code:
|
|
|
|
1. **`host_permissions` is deliberately narrow** — the firm sites plus localhost
|
|
for the dashboard. The extension is *technically incapable* of reading any
|
|
other site, so an accidental capture of your bank or mail tab cannot happen
|
|
however the logic here is changed.
|
|
2. **Only the tab you are on.** `pickTab()` asks for the active tab of the
|
|
last-focused window *and* a host_permissions match. A firm tab sitting in the
|
|
background is not captured, and neither is anything else. Switch away and
|
|
capture simply stops until you switch back.
|
|
3. **One content script, same hosts.** `captcha-hook.js` runs at document_start
|
|
on the firm sites only. It wraps `turnstile.render` / `grecaptcha.render` /
|
|
`hcaptcha.render` and remembers what the page passed them — the sitekey, and
|
|
above all the callback a solved token has to be handed to, which a
|
|
programmatically rendered widget puts nowhere else. It reads nothing else and
|
|
sends nothing anywhere; the remembered arguments stay in the page's own world
|
|
until a `solveCaptcha` step comes to collect them.
|
|
|
|
To automate a different broker, add its pattern to `host_permissions` in
|
|
`manifest.json` and reload the extension — that alone scopes capture to it. Avoid
|
|
going back to `<all_urls>`: it would put every tab you visit in reach, and limit
|
|
1 is the only thing standing between this and scraping your whole browser. A new
|
|
firm needs its host in *both* lists — `host_permissions` and the `content_scripts`
|
|
matches — or captchas on that site will have no callback to fire.
|
|
|
|
## Notes
|
|
|
|
- The extension never captures the dashboard's own pages — otherwise it would
|
|
just mirror its own output back.
|
|
- `chrome://`, `about:` and Web Store pages cannot be scripted by any extension;
|
|
they're skipped.
|
|
- MV3 service workers are torn down when idle. Each poll makes an extension API
|
|
call, which keeps the worker alive; a 30-second alarm revives it if Chrome
|
|
kills it anyway. So worst-case cadence is 30s, normal cadence is the poll
|
|
interval.
|