- Centralize all magic numbers/strings in lib/constants.mjs - Fix double-replaced import names in filter.mjs - Consolidate duplicate fs imports in job_applier/job_searcher - Remove empty JSDoc block in job_searcher - Update keywords.mjs model from claude-3-haiku to claude-haiku-4-5 - Extract Anthropic API URLs to constants - Convert :has-text() selectors to page.locator() API - Fix SIGTERM handler conflict — move partial-run notification into lock.onShutdown - Remove unused exports (LOCAL_USER_AGENT, DEFAULT_REVIEW_WINDOW_MINUTES) - Fix variable shadowing (b -> v) in job_filter reduce callback - Replace SKILL.md PM2 references with system cron Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
38 lines
1.4 KiB
JavaScript
38 lines
1.4 KiB
JavaScript
/**
|
|
* wellfound.mjs — Wellfound apply handler
|
|
*/
|
|
import {
|
|
NAVIGATION_TIMEOUT, PAGE_LOAD_WAIT, FORM_FILL_WAIT, SUBMIT_WAIT
|
|
} from '../constants.mjs';
|
|
|
|
export const SUPPORTED_TYPES = ['wellfound', 'wellfound_apply'];
|
|
|
|
export async function apply(page, job, formFiller) {
|
|
await page.goto(job.url, { waitUntil: 'domcontentloaded', timeout: NAVIGATION_TIMEOUT });
|
|
await page.waitForTimeout(PAGE_LOAD_WAIT);
|
|
|
|
const meta = await page.evaluate(() => ({
|
|
title: document.querySelector('h1')?.textContent?.trim(),
|
|
company: document.querySelector('[class*="company"] h2, [class*="startup"] h2, h2')?.textContent?.trim(),
|
|
}));
|
|
|
|
const applyBtn = page.locator('a:has-text("Apply"), button:has-text("Apply Now"), a:has-text("Apply Now")').first();
|
|
if (await applyBtn.count() === 0) return { status: 'no_button', meta };
|
|
|
|
await applyBtn.click();
|
|
await page.waitForTimeout(FORM_FILL_WAIT);
|
|
|
|
const unknowns = await formFiller.fill(page, formFiller.profile.resume_path);
|
|
|
|
if (unknowns[0]?.honeypot) return { status: 'skipped_honeypot', meta };
|
|
if (unknowns.length > 0) return { status: 'needs_answer', pending_question: unknowns[0], meta };
|
|
|
|
const submitBtn = await page.$('button[type="submit"]:not([disabled]), input[type="submit"]');
|
|
if (!submitBtn) return { status: 'no_submit', meta };
|
|
|
|
await submitBtn.click();
|
|
await page.waitForTimeout(SUBMIT_WAIT);
|
|
|
|
return { status: 'submitted', meta };
|
|
}
|