diff --git a/job_applier.mjs b/job_applier.mjs index 7f164bc..75a2c0c 100644 --- a/job_applier.mjs +++ b/job_applier.mjs @@ -50,7 +50,10 @@ async function main() { return; } - const results = { submitted: 0, skipped: 0, failed: 0, needs_answer: 0, total: jobs.length }; + const results = { + submitted: 0, failed: 0, needs_answer: 0, total: jobs.length, + skipped_recruiter: 0, skipped_external: 0, skipped_no_easy_apply: 0 + }; // Group by platform const liJobs = jobs.filter(j => j.platform === 'linkedin'); @@ -154,12 +157,27 @@ async function handleResult(job, result, results, settings) { results.skipped++; break; + case 'skipped_recruiter_only': + console.log(` ⏭️ Skipped — recruiter-only ("I'm interested")`); + updateJobStatus(job.id, 'skipped_recruiter_only', { title, company }); + appendLog({ ...job, title, company, status: 'skipped_recruiter_only' }); + results.skipped_recruiter++; + break; + + case 'skipped_external_unsupported': + console.log(` ⏭️ Skipped — external ATS (not yet supported)`); + updateJobStatus(job.id, 'skipped_external_unsupported', { title, company }); + appendLog({ ...job, title, company, status: 'skipped_external_unsupported' }); + results.skipped_external++; + break; + + case 'skipped_easy_apply_unsupported': case 'no_easy_apply': case 'no_button': - console.log(` ⏭️ Skipped — no apply button`); - updateJobStatus(job.id, 'skipped', { notes: status, title, company }); - appendLog({ ...job, title, company, status: 'skipped', notes: status }); - results.skipped++; + console.log(` ⏭️ Skipped — no Easy Apply`); + updateJobStatus(job.id, 'skipped_easy_apply_unsupported', { title, company }); + appendLog({ ...job, title, company, status: 'skipped_easy_apply_unsupported' }); + results.skipped_no_easy_apply++; break; default: diff --git a/lib/linkedin.mjs b/lib/linkedin.mjs index 2459ba3..5fb8d5b 100644 --- a/lib/linkedin.mjs +++ b/lib/linkedin.mjs @@ -93,9 +93,14 @@ export async function applyLinkedIn(page, job, formFiller) { company: document.querySelector('.job-details-jobs-unified-top-card__company-name a, .jobs-unified-top-card__company-name a')?.textContent?.trim(), })); - // Find Easy Apply button + // Detect apply type const eaBtn = await page.$('button.jobs-apply-button[aria-label*="Easy Apply"]'); - if (!eaBtn) return { status: 'no_easy_apply', meta }; + const externalBtn = await page.$('button.jobs-apply-button:not([aria-label*="Easy Apply"])'); + const interestedBtn = await page.$('button[aria-label*="interested"], button:has-text("I\'m interested")'); + + if (!eaBtn && interestedBtn) return { status: 'skipped_recruiter_only', meta }; + if (!eaBtn && externalBtn) return { status: 'skipped_external_unsupported', meta }; + if (!eaBtn) return { status: 'skipped_easy_apply_unsupported', meta }; // Click Easy Apply await page.click('button.jobs-apply-button', { timeout: 5000 }).catch(() => {}); diff --git a/lib/notify.mjs b/lib/notify.mjs index 31b3852..00b6660 100644 --- a/lib/notify.mjs +++ b/lib/notify.mjs @@ -34,13 +34,16 @@ export function formatSearchSummary(added, skipped, platforms) { } export function formatApplySummary(results) { - const { submitted, skipped, failed, needs_answer, total } = results; + const { submitted, failed, needs_answer, total, + skipped_recruiter, skipped_external, skipped_no_easy_apply } = results; const lines = [ `✅ *Apply Run Complete*`, - `Applied: ${submitted} | Skipped: ${skipped} | Failed: ${failed} | Needs answer: ${needs_answer}`, + `Applied: ${submitted} | Failed: ${failed} | Needs answer: ${needs_answer}`, + `Skipped: ${skipped_recruiter} recruiter-only | ${skipped_external} external ATS | ${skipped_no_easy_apply} no Easy Apply`, `Total processed: ${total}`, ]; if (needs_answer > 0) lines.push(`\n💬 Check messages — I sent questions that need your answers`); + if (skipped_external > 0) lines.push(`\n🔜 ${skipped_external} external ATS jobs saved for when Greenhouse/Lever support lands`); return lines.join('\n'); } diff --git a/node_modules b/node_modules new file mode 120000 index 0000000..867c978 --- /dev/null +++ b/node_modules @@ -0,0 +1 @@ +/home/ubuntu/.openclaw/workspace/node_modules \ No newline at end of file