import fs from "node:fs"; import type { Adapter } from "./index"; import { launchPage, fillIfPresent } from "./index"; /** DataAnnotation worker signup (app.dataannotation.tech/worker_signup). */ export const dataAnnotationAdapter: Adapter = { name: "dataannotation", matches: (url) => url.includes("dataannotation.tech"), async run({ job, profile, submit }) { const lines: string[] = []; fs.mkdirSync("worker/out", { recursive: true }); const { browser, page } = await launchPage(); try { await page.goto(job.applyUrl ?? job.url ?? "", { waitUntil: "domcontentloaded" }); lines.push(`opened ${page.url()}`); await page.screenshot({ path: "worker/out/da-1-landing.png", fullPage: true }); const [first, ...rest] = (profile.fullName ?? "").split(" "); await fillIfPresent(page, ['input[name="first_name"]', "#first_name"], first, lines); await fillIfPresent(page, ['input[name="last_name"]', "#last_name"], rest.join(" "), lines); await fillIfPresent(page, ['input[type="email"]', 'input[name="email"]'], profile.email, lines); await page.screenshot({ path: "worker/out/da-2-filled.png", fullPage: true }); // CAPTCHA / verification: give the human 90s in the headed browser. if (await page.locator('iframe[src*="captcha"], iframe[src*="turnstile"]').count()) { lines.push("CAPTCHA detected — waiting 90s for manual solve"); await page.waitForTimeout(90_000); } if (!submit) { lines.push("dry run: stopping before submit"); return { submitted: false, lines }; } const btn = page.locator('button[type="submit"]').first(); if (!(await btn.count())) { lines.push("no submit button found — aborting"); return { submitted: false, lines }; } await btn.click(); await page.waitForLoadState("networkidle"); await page.screenshot({ path: "worker/out/da-3-submitted.png", fullPage: true }); lines.push(`submitted; landed on ${page.url()}`); return { submitted: true, lines }; } finally { await browser.close(); } }, };