Fix CAPTCHA detection to allow invisible reCAPTCHA
Invisible reCAPTCHA (size=invisible) fires on submit and usually passes automatically. Only block on visible CAPTCHA challenges. Also fix form detection to work without <form> wrapper elements. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,7 +32,14 @@ export async function apply(page, job, formFiller) {
|
|||||||
const hasLogin = !!(document.querySelector('input[type="password"]') ||
|
const hasLogin = !!(document.querySelector('input[type="password"]') ||
|
||||||
(text.includes('sign in') && text.includes('create account')) ||
|
(text.includes('sign in') && text.includes('create account')) ||
|
||||||
(text.includes('log in') && text.includes('register')));
|
(text.includes('log in') && text.includes('register')));
|
||||||
const hasCaptcha = !!(document.querySelector('iframe[src*="recaptcha"], iframe[src*="captcha"], [class*="captcha"]'));
|
// Only block on visible CAPTCHAs — invisible reCAPTCHA (size=invisible) fires on submit and usually passes
|
||||||
|
const captchaFrames = Array.from(document.querySelectorAll('iframe[src*="recaptcha"], iframe[src*="captcha"]'));
|
||||||
|
const hasVisibleCaptcha = captchaFrames.some(f => {
|
||||||
|
if (f.src.includes('size=invisible')) return false;
|
||||||
|
const rect = f.getBoundingClientRect();
|
||||||
|
return rect.width > 50 && rect.height > 50;
|
||||||
|
});
|
||||||
|
const hasCaptcha = hasVisibleCaptcha;
|
||||||
const isClosed = text.includes('no longer accepting') || text.includes('position has been filled') ||
|
const isClosed = text.includes('no longer accepting') || text.includes('position has been filled') ||
|
||||||
text.includes('this job is no longer') || text.includes('job not found') ||
|
text.includes('this job is no longer') || text.includes('job not found') ||
|
||||||
text.includes('this position is closed') || text.includes('listing has expired');
|
text.includes('this position is closed') || text.includes('listing has expired');
|
||||||
@@ -44,7 +51,8 @@ export async function apply(page, job, formFiller) {
|
|||||||
if (pageCheck.hasCaptcha) return { status: 'skipped_captcha', meta };
|
if (pageCheck.hasCaptcha) return { status: 'skipped_captcha', meta };
|
||||||
|
|
||||||
// Some pages land directly on the form; others need an Apply button click
|
// Some pages land directly on the form; others need an Apply button click
|
||||||
const hasFormAlready = await page.$('form input[type="text"], form input[type="email"], form textarea');
|
// Check if we landed directly on a form (with or without <form> wrapper)
|
||||||
|
const hasFormAlready = await page.$('input[type="text"], input[type="email"], textarea');
|
||||||
if (!hasFormAlready) {
|
if (!hasFormAlready) {
|
||||||
const applyBtn = page.locator([
|
const applyBtn = page.locator([
|
||||||
'a:has-text("Apply Now")',
|
'a:has-text("Apply Now")',
|
||||||
@@ -76,7 +84,8 @@ export async function apply(page, job, formFiller) {
|
|||||||
// Re-check for blockers after click
|
// Re-check for blockers after click
|
||||||
const postClick = await page.evaluate(() => ({
|
const postClick = await page.evaluate(() => ({
|
||||||
hasLogin: !!document.querySelector('input[type="password"]'),
|
hasLogin: !!document.querySelector('input[type="password"]'),
|
||||||
hasCaptcha: !!document.querySelector('iframe[src*="recaptcha"], [class*="captcha"]'),
|
hasCaptcha: Array.from(document.querySelectorAll('iframe[src*="recaptcha"], iframe[src*="captcha"]'))
|
||||||
|
.some(f => !f.src.includes('size=invisible') && f.getBoundingClientRect().width > 50),
|
||||||
})).catch(() => ({}));
|
})).catch(() => ({}));
|
||||||
if (postClick.hasLogin) return { status: 'skipped_login_required', meta };
|
if (postClick.hasLogin) return { status: 'skipped_login_required', meta };
|
||||||
if (postClick.hasCaptcha) return { status: 'skipped_captcha', meta };
|
if (postClick.hasCaptcha) return { status: 'skipped_captcha', meta };
|
||||||
|
|||||||
Reference in New Issue
Block a user