fiptcha 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/captcha-grid-solver.js +17 -6
package/package.json
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const { captchaModelManager, checksumBuffer } = require('./captcha-model-manager');
|
|
2
|
-
const { clickVisibleTarget } = require('./captcha-pointer');
|
|
3
2
|
|
|
4
3
|
const PROVIDERS = Object.freeze({
|
|
5
4
|
recaptcha_v2: Object.freeze({
|
|
@@ -127,6 +126,16 @@ async function classifyGrid(frame, adapter, cells, label, seenTiles) {
|
|
|
127
126
|
return selected;
|
|
128
127
|
}
|
|
129
128
|
|
|
129
|
+
async function rememberClickedTile(cells, index, seenTiles) {
|
|
130
|
+
// Clicking a CAPTCHA tile changes its rendered appearance (selection overlay,
|
|
131
|
+
// border, checkmark, etc.). Remember that post-click state immediately so the
|
|
132
|
+
// next sweep does not mistake the selection UI itself for a replacement image
|
|
133
|
+
// and toggle an already-correct tile back off. A genuinely replaced tile will
|
|
134
|
+
// still produce a different fingerprint on the next sweep.
|
|
135
|
+
const image = await cells.nth(index).screenshot({ type: 'png' }).catch(() => null);
|
|
136
|
+
if (image) seenTiles.set(index, checksumBuffer(image));
|
|
137
|
+
}
|
|
138
|
+
|
|
130
139
|
async function visibleText(frame, selector) {
|
|
131
140
|
const matches = frame.locator(selector);
|
|
132
141
|
for (let index = 0; index < await matches.count().catch(() => 0); index += 1) {
|
|
@@ -161,17 +170,19 @@ async function solveImageGrid(page, { captchaType, deadline, waitForToken, logs
|
|
|
161
170
|
const count = await cells.count();
|
|
162
171
|
if (![9, 16].includes(count)) throw new Error(`Unsupported ${captchaType} grid size (${count} cells)`);
|
|
163
172
|
const selected = await classifyGrid(frame, adapter, cells, prompt, seenTiles);
|
|
173
|
+
// Grid cells live inside a provider iframe. Let Playwright target the
|
|
174
|
+
// element in that frame instead of sending a page-level mouse click:
|
|
175
|
+
// the latter can miss the cell when iframe coordinates change.
|
|
164
176
|
for (const index of selected) {
|
|
165
|
-
|
|
166
|
-
|
|
177
|
+
await cells.nth(index).click({ timeout: 2000 });
|
|
178
|
+
await rememberClickedTile(cells, index, seenTiles);
|
|
167
179
|
}
|
|
168
180
|
totalSelections += selected.length;
|
|
169
181
|
if (!selected.length) break;
|
|
170
182
|
await page.waitForTimeout(600);
|
|
171
183
|
}
|
|
172
184
|
logs.push(`Local ${captchaType} grid round ${round + 1}: selected ${totalSelections} cells for "${prompt}"`);
|
|
173
|
-
|
|
174
|
-
if (!submitted) throw new Error(`${captchaType} verification button was outside the viewport`);
|
|
185
|
+
await frame.locator(totalSelections ? adapter.submit : adapter.noMatch).first().click({ timeout: 2000 });
|
|
175
186
|
const token = await waitForToken(page, captchaType, Math.min(2500, Math.max(0, deadline - Date.now())));
|
|
176
187
|
if (token) return token;
|
|
177
188
|
await page.waitForTimeout(350);
|
|
@@ -179,4 +190,4 @@ async function solveImageGrid(page, { captchaType, deadline, waitForToken, logs
|
|
|
179
190
|
return null;
|
|
180
191
|
}
|
|
181
192
|
|
|
182
|
-
module.exports = { PROVIDERS, normalizePrompt, normalizeModelLabel, normalizeBox, pngDimensions, mapDetectionsToCells, classifyGrid, visibleText, solveImageGrid };
|
|
193
|
+
module.exports = { PROVIDERS, normalizePrompt, normalizeModelLabel, normalizeBox, pngDimensions, mapDetectionsToCells, classifyGrid, rememberClickedTile, visibleText, solveImageGrid };
|