entrox-bypass 0.2.0 → 0.3.0
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/README.md +248 -149
- package/dist/index.cjs +407 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +388 -61
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/types/index.d.ts +84 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/llm.ts","../src/cloudinary.ts","../src/captchaSolve.ts","../src/login.ts","../src/index.ts"],"sourcesContent":["import \"dotenv/config\";\nimport { ChatOpenAI } from \"@langchain/openai\";\nimport { HumanMessage } from \"@langchain/core/messages\";\n\ninterface CaptchaResult {\n text: string;\n description: string;\n}\n\nclass LlmError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LlmError';\n }\n}\n\nconst model = new ChatOpenAI({\n model: process.env.LLM_MODEL || \"google/gemma-4-26b-a4b-it\",\n temperature: 0,\n apiKey: process.env.OPENROUTER_API_KEY,\n configuration: {\n baseURL: \"https://openrouter.ai/api/v1\",\n },\n});\n\nconst getImageDetails = async function (image_url: string): Promise<CaptchaResult> {\n if (!process.env.OPENROUTER_API_KEY) {\n throw new LlmError('OPENROUTER_API_KEY environment variable is required');\n }\n\n const response = await model.invoke([\n new HumanMessage({\n content: [\n {\n type: \"text\",\n text: `You are a CAPTCHA solving assistant. Analyze the provided image and return the following in strict JSON format:\n- \"text\": The exact text or characters shown in the CAPTCHA\n- \"description\": A brief description of what appears in the image\n\nIf there is no text in the image, set \"text\" to \"no text found\".\n\nExample response:\n{\"text\": \"X7K9P\", \"description\": \"Black text on white background showing alphanumeric characters\"}\n\nReturn ONLY valid JSON with no markdown formatting.`,\n },\n {\n type: \"image_url\",\n image_url: {\n url: image_url,\n },\n },\n ],\n }),\n ]);\n\n const content = response.content as string | Array<any>;\n \n if (typeof content === 'string') {\n const jsonString = content\n .replace(/```json\\s*/i, '')\n .replace(/```\\s*$/, '')\n .trim();\n \n try {\n return JSON.parse(jsonString);\n } catch (parseError) {\n throw new LlmError(`Failed to parse LLM response as JSON: ${parseError}`);\n }\n }\n \n throw new LlmError('Unexpected LLM response format');\n};\n\nexport default getImageDetails;\nexport type { CaptchaResult };\nexport { LlmError };\n","import 'dotenv/config';\nimport { v2 as cloudinary } from 'cloudinary';\n\ninterface CloudinaryConfig {\n cloud_name: string;\n api_key: string;\n api_secret: string;\n}\n\nclass CloudinaryError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CloudinaryError';\n }\n}\n\nfunction validateConfig(config: CloudinaryConfig): void {\n const missing: string[] = [];\n \n if (!config.cloud_name) missing.push('CLOUDINARY_CLOUD_NAME');\n if (!config.api_key) missing.push('CLOUDINARY_API_KEY');\n if (!config.api_secret) missing.push('CLOUDINARY_API_SECRET');\n \n if (missing.length > 0) {\n throw new CloudinaryError(`Missing Cloudinary credentials: ${missing.join(', ')}`);\n }\n}\n\nexport interface UploadResult {\n secure_url: string;\n public_id: string;\n format: string;\n width: number;\n height: number;\n bytes: number;\n resource_type: string;\n original_filename: string;\n}\n\nexport function getConfig(): CloudinaryConfig {\n return {\n cloud_name: process.env.CLOUDINARY_CLOUD_NAME || '',\n api_key: process.env.CLOUDINARY_API_KEY || '',\n api_secret: process.env.CLOUDINARY_API_SECRET || '',\n };\n}\n\nconst config = getConfig();\nvalidateConfig(config);\n\ncloudinary.config(config);\n\nexport default cloudinary;\nexport { CloudinaryError };\n","import { Page } from \"playwright\";\nimport getImageDetails, { CaptchaResult } from \"./llm.js\";\nimport cloudinary from \"./cloudinary.js\";\n\ninterface ScreenshotError extends Error {\n code: string;\n}\n\nexport async function solveCaptchaFromPage(\n page: Page,\n captchaSelector: string = \"img.captcha-image\",\n outputScreenshotPath?: string\n): Promise<CaptchaResult> {\n const captchaImage = page.locator(captchaSelector);\n\n try {\n await captchaImage.waitFor({ state: \"visible\" });\n } catch (error) {\n throw new Error(`CAPTCHA element not found or not visible. Selector: ${captchaSelector}`);\n }\n\n if (outputScreenshotPath) {\n await captchaImage.screenshot({ path: outputScreenshotPath });\n }\n\n let imageData: { mimeType: string; base64: string };\n\n try {\n imageData = await captchaImage.evaluate(async (img: HTMLImageElement) => {\n const response = await fetch(img.src);\n\n if (!response.ok) {\n throw new Error(`Image fetch failed: ${response.status}`);\n }\n\n const blob = await response.blob();\n\n return new Promise<{ mimeType: string; base64: string }>((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => {\n const result = reader.result as string;\n const base64 = result.split(\",\")[1];\n resolve({\n mimeType: blob.type || \"image/png\",\n base64,\n });\n };\n\n reader.onerror = reject;\n reader.readAsDataURL(blob);\n });\n });\n } catch (error) {\n throw new Error(`Failed to extract CAPTCHA image: ${error}`);\n }\n\n let uploadResult;\n\n try {\n uploadResult = await cloudinary.uploader.upload(\n `data:${imageData.mimeType};base64,${imageData.base64}`,\n {\n folder: \"playwright-captcha-images\",\n resource_type: \"image\",\n type: \"auth\",\n }\n );\n } catch (error) {\n throw new Error(`Failed to upload CAPTCHA image to Cloudinary: ${error}`);\n }\n\n const imageUrl = uploadResult.secure_url;\n\n try {\n const result = await getImageDetails(imageUrl);\n return result;\n } catch (error) {\n throw new Error(`Failed to solve CAPTCHA using AI: ${error}`);\n }\n}\n","import { chromium, Browser, Page, BrowserContext } from \"playwright\";\nimport { solveCaptchaFromPage } from \"./captchaSolve.js\";\n\nexport interface LoginOptions {\n url: string;\n loginSelector?: string;\n passwordSelector?: string;\n captchaInputSelector?: string;\n submitButtonSelector?: string;\n headless?: boolean;\n outputScreenshotPath?: string;\n screenshotDelay?: number;\n}\n\nexport interface LoginResult {\n success: boolean;\n url: string;\n title: string;\n page: Page;\n error?: string;\n}\n\nclass BrowserError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'BrowserError';\n }\n}\n\nasync function validateEnv(): Promise<void> {\n const missing: string[] = [];\n \n if (!process.env.EMAIL || process.env.EMAIL === 'dev@example.com') {\n missing.push('EMAIL - Set to actual email address');\n }\n if (!process.env.PASSWORD || process.env.PASSWORD === '22222222') {\n missing.push('PASSWORD - Set to actual password');\n }\n \n if (missing.length > 0) {\n console.warn('Warning: The following environment variables are set to defaults or missing:');\n missing.forEach(m => console.warn(` - ${m}`));\n console.warn('Please update your .env file with real credentials.');\n }\n}\n\nexport async function automateLogin(options: LoginOptions): Promise<LoginResult> {\n let browser: Browser | null = null;\n let context: BrowserContext | null = null;\n let page: Page | null = null;\n\n try {\n await validateEnv();\n\n browser = await chromium.launch({\n headless: options.headless ?? false,\n });\n\n context = await browser.newContext();\n page = await context.newPage();\n\n await page.goto(options.url, { waitUntil: \"domcontentloaded\" });\n\n const loginSelector = options.loginSelector || \"#login\";\n const passwordSelector = options.passwordSelector || \"#password\";\n const captchaSelector = \"img.captcha-image\";\n const captchaInputSelector = options.captchaInputSelector || \"#captcha\";\n const submitButtonSelector = options.submitButtonSelector || \"button[type='submit']\";\n\n await page.locator(loginSelector).fill(process.env.EMAIL || \"\");\n await page.locator(passwordSelector).fill(process.env.PASSWORD || \"\");\n\n const captchaResult = await solveCaptchaFromPage(\n page,\n captchaSelector,\n options.outputScreenshotPath ? undefined : undefined\n );\n\n await page.locator(captchaInputSelector).fill(captchaResult.text);\n await page.locator(submitButtonSelector).click();\n\n try {\n await page.waitForLoadState(\"domcontentloaded\", { timeout: 15000 });\n \n if (options.screenshotDelay) {\n await page.waitForTimeout(options.screenshotDelay);\n }\n\n if (options.outputScreenshotPath) {\n await page.screenshot({ path: options.outputScreenshotPath, fullPage: true });\n }\n } catch (error) {\n console.warn('Warning: Could not wait for post-login state:', error);\n }\n\n return {\n success: true,\n url: page.url(),\n title: await page.title(),\n page,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n \n let pageTitle = '';\n if (page) {\n try {\n pageTitle = await page.title();\n } catch {\n pageTitle = 'failed to get title';\n }\n }\n \n return {\n success: false,\n url: page?.url() || '',\n title: pageTitle,\n page: page!,\n error: errorMessage,\n };\n } finally {\n if (browser && !options.headless) {\n await browser.close().catch(() => {});\n }\n }\n}\n","import { solveCaptchaFromPage } from \"./captchaSolve.js\";\nimport { automateLogin, LoginOptions, LoginResult } from \"./login.js\";\n\nexport type { CaptchaResult } from \"./llm.js\";\nexport type { LoginOptions, LoginResult } from \"./login.js\";\n\nexport { solveCaptchaFromPage };\nexport { automateLogin };\n\nexport default {\n solveCaptchaFromPage,\n automateLogin,\n};\n"],"mappings":"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","names":["config"]}
|
|
1
|
+
{"version":3,"sources":["../src/llm.ts","../src/cloudinary.ts","../src/utils/retry.ts","../src/captchaSolve.ts","../src/login.ts","../src/utils/humanDelay.ts","../src/index.ts"],"sourcesContent":["import \"dotenv/config\";\nimport { ChatOpenAI } from \"@langchain/openai\";\nimport { HumanMessage } from \"@langchain/core/messages\";\n\ninterface CaptchaResult {\n text: string;\n description: string;\n}\n\nclass LlmError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LlmError';\n }\n}\n\nconst model = new ChatOpenAI({\n model: process.env.LLM_MODEL || \"google/gemma-4-26b-a4b-it\",\n temperature: 0,\n apiKey: process.env.OPENROUTER_API_KEY,\n configuration: {\n baseURL: \"https://openrouter.ai/api/v1\",\n },\n});\n\nconst getImageDetails = async function (image_url: string): Promise<CaptchaResult> {\n if (!process.env.OPENROUTER_API_KEY) {\n throw new LlmError('OPENROUTER_API_KEY environment variable is required');\n }\n\n const response = await model.invoke([\n new HumanMessage({\n content: [\n {\n type: \"text\",\n text: `You are a CAPTCHA solving assistant. Analyze the provided image and return the following in strict JSON format:\n- \"text\": The exact text or characters shown in the CAPTCHA\n- \"description\": A brief description of what appears in the image\n\nIf there is no text in the image, set \"text\" to \"no text found\".\n\nExample response:\n{\"text\": \"X7K9P\", \"description\": \"Black text on white background showing alphanumeric characters\"}\n\nReturn ONLY valid JSON with no markdown formatting.`,\n },\n {\n type: \"image_url\",\n image_url: {\n url: image_url,\n },\n },\n ],\n }),\n ]);\n\n const content = response.content as string | Array<any>;\n \n if (typeof content === 'string') {\n const jsonString = content\n .replace(/```json\\s*/i, '')\n .replace(/```\\s*$/, '')\n .trim();\n \n try {\n return JSON.parse(jsonString);\n } catch (parseError) {\n throw new LlmError(`Failed to parse LLM response as JSON: ${parseError}`);\n }\n }\n \n throw new LlmError('Unexpected LLM response format');\n};\n\nexport default getImageDetails;\nexport type { CaptchaResult };\nexport { LlmError };\n","import 'dotenv/config';\nimport { v2 as cloudinary } from 'cloudinary';\n\ninterface CloudinaryConfig {\n cloud_name: string;\n api_key: string;\n api_secret: string;\n}\n\nclass CloudinaryError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CloudinaryError';\n }\n}\n\nfunction validateConfig(config: CloudinaryConfig): void {\n const missing: string[] = [];\n \n if (!config.cloud_name) missing.push('CLOUDINARY_CLOUD_NAME');\n if (!config.api_key) missing.push('CLOUDINARY_API_KEY');\n if (!config.api_secret) missing.push('CLOUDINARY_API_SECRET');\n \n if (missing.length > 0) {\n throw new CloudinaryError(`Missing Cloudinary credentials: ${missing.join(', ')}`);\n }\n}\n\nexport interface UploadResult {\n secure_url: string;\n public_id: string;\n format: string;\n width: number;\n height: number;\n bytes: number;\n resource_type: string;\n original_filename: string;\n}\n\nexport function getConfig(): CloudinaryConfig {\n return {\n cloud_name: process.env.CLOUDINARY_CLOUD_NAME || '',\n api_key: process.env.CLOUDINARY_API_KEY || '',\n api_secret: process.env.CLOUDINARY_API_SECRET || '',\n };\n}\n\nconst config = getConfig();\nvalidateConfig(config);\n\ncloudinary.config(config);\n\nexport default cloudinary;\nexport { CloudinaryError };\n","import { LlmError } from \"../llm.js\";\n\nexport interface RetryableError extends Error {\n name: string;\n retryable?: boolean;\n}\n\nconst RETRYABLE_ERROR_NAMES = new Set([\n \"TimeoutError\",\n \"NetworkError\",\n \"PlaywrightError\",\n \"LlmError\",\n \"CloudinaryError\",\n \"FetchError\",\n \"RateLimitError\",\n \"RetryableError\",\n]);\n\nexport function isRetryable(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n\n const err = error as Partial<{ name: string; message: string }>;\n\n if (err.name && RETRYABLE_ERROR_NAMES.has(err.name)) {\n return true;\n }\n\n if (typeof err.message === \"string\") {\n const lowerMessage = err.message.toLowerCase();\n if (\n lowerMessage.includes(\"timeout\") ||\n lowerMessage.includes(\"network\") ||\n lowerMessage.includes(\"refused\") ||\n lowerMessage.includes(\"reset\") ||\n lowerMessage.includes(\"rate limit\") ||\n lowerMessage.includes(\"too many requests\") ||\n lowerMessage.includes(\"unavailable\")\n ) {\n return true;\n }\n }\n\n return false;\n}\n\nexport interface RetryOptions {\n maxAttempts?: number;\n delayMs?: number;\n multiplier?: number;\n onRetry?: (attempt: number, error: unknown, totalDelay: number) => void;\n}\n\nexport async function retry<T>(\n fn: () => Promise<T>,\n options?: RetryOptions\n): Promise<T> {\n const maxAttempts = options?.maxAttempts ?? 3;\n const initialDelay = options?.delayMs ?? 1000;\n const multiplier = options?.multiplier ?? 2;\n const onRetry = options?.onRetry;\n\n let lastError: unknown;\n let totalDelay = 0;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n\n if (!isRetryable(error) || attempt >= maxAttempts) {\n break;\n }\n\n const waitTime = initialDelay * Math.pow(multiplier, attempt - 1);\n totalDelay += waitTime;\n\n if (onRetry) {\n onRetry(attempt, error, totalDelay);\n }\n\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n }\n }\n\n throw lastError;\n}\n","import { Page } from \"playwright\";\nimport getImageDetails, { CaptchaResult, LlmError } from \"./llm.js\";\nimport cloudinary from \"./cloudinary.js\";\nimport { retry } from \"./utils/retry.js\";\n\nexport interface SolveCaptchaOptions {\n /** Max attempts for image fetch / LLM call chain. Default 3. */\n maxRetries?: number;\n /** Initial delay in ms before first retry. Default 1000. */\n retryDelayMs?: number;\n /** Multiplier applied to retryDelayMs per attempt. Default 2. */\n retryMultiplier?: number;\n /** Timeout in ms for the image fetch + upload + LLM sequence. Default 60000. */\n timeoutMs?: number;\n}\n\nexport async function solveCaptchaFromPage(\n page: Page,\n captchaSelector: string = \"img.captcha-image\",\n outputScreenshotPath?: string,\n options?: SolveCaptchaOptions\n): Promise<CaptchaResult> {\n const maxRetries = options?.maxRetries ?? 3;\n const retryDelay = options?.retryDelayMs ?? 1000;\n const retryMultiplier = options?.retryMultiplier ?? 2;\n\n const captchaImage = page.locator(captchaSelector);\n\n try {\n await captchaImage.waitFor({ state: \"visible\" });\n } catch (error) {\n throw new Error(`CAPTCHA element not found or not visible. Selector: ${captchaSelector}`);\n }\n\n if (outputScreenshotPath) {\n await captchaImage.screenshot({ path: outputScreenshotPath });\n }\n\n // ---- Extract image as base64 (retries on network errors) ----------\n let imageData: { mimeType: string; base64: string };\n\n try {\n imageData = await retry(\n async () => {\n return await captchaImage.evaluate(async (img: HTMLImageElement) => {\n const response = await fetch(img.src);\n if (!response.ok) {\n throw new Error(`Image fetch failed: ${response.status}`);\n }\n const blob = await response.blob();\n return new Promise<{ mimeType: string; base64: string }>((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const result = reader.result as string;\n resolve({\n mimeType: blob.type || \"image/png\",\n base64: result.split(\",\")[1],\n });\n };\n reader.onerror = reject;\n reader.readAsDataURL(blob);\n });\n });\n },\n {\n maxAttempts: maxRetries,\n delayMs: retryDelay,\n multiplier: retryMultiplier,\n }\n );\n } catch (error) {\n throw new Error(`Failed to extract CAPTCHA image: ${error}`);\n }\n\n // ---- Upload to Cloudinary (retries on network errors) -------------\n let uploadResult;\n\n try {\n uploadResult = await retry(\n async () => {\n return await cloudinary.uploader.upload(\n `data:${imageData.mimeType};base64,${imageData.base64}`,\n {\n folder: \"playwright-captcha-images\",\n resource_type: \"image\",\n type: \"auth\",\n }\n );\n },\n {\n maxAttempts: maxRetries,\n delayMs: retryDelay,\n multiplier: retryMultiplier,\n }\n );\n } catch (error) {\n throw new Error(`Failed to upload CAPTCHA image to Cloudinary: ${error}`);\n }\n\n const imageUrl = uploadResult.secure_url;\n\n // ---- LLM solve (retries on timeout / rate-limit) ------------------\n try {\n const result = await retry(\n async () => {\n return await getImageDetails(imageUrl);\n },\n {\n maxAttempts: maxRetries,\n delayMs: retryDelay,\n multiplier: retryMultiplier,\n }\n );\n return result;\n } catch (error) {\n throw new Error(`Failed to solve CAPTCHA using AI: ${error}`);\n }\n}\n","import { chromium, Browser, Page, BrowserContext } from \"playwright\";\nimport { solveCaptchaFromPage } from \"./captchaSolve.js\";\nimport { retry, isRetryable } from \"./utils/retry.js\";\nimport { delay, randomBetween, executeWithRandomDelay } from \"./utils/humanDelay.js\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface LoginOptions {\n // Existing\n url: string;\n loginSelector?: string;\n passwordSelector?: string;\n captchaInputSelector?: string;\n submitButtonSelector?: string;\n headless?: boolean;\n outputScreenshotPath?: string;\n screenshotDelay?: number;\n\n // New – credentials override\n email?: string;\n password?: string;\n\n // New – retry\n retryCount?: number;\n baseRetryDelay?: number;\n\n // New – human-like timing\n delayRange?: { min: number; max: number };\n\n // New – proxy\n proxy?: { server: string; username?: string; password?: string };\n\n // New – session persistence\n cookieFile?: string;\n\n // New – video recording\n videoPath?: string;\n\n // New – webhook notifications\n webhookUrl?: string;\n}\n\nexport interface LoginResult {\n success: boolean;\n url: string;\n title: string;\n page: Page;\n error?: string;\n}\n\ninterface SerializedCookie {\n name: string;\n value: string;\n domain: string;\n path: string;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"Strict\" | \"Lax\" | \"None\";\n expires?: number;\n rawExpires?: string;\n}\n\nclass BrowserError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BrowserError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function validateEnv(options: LoginOptions): Promise<void> {\n const email = options.email || process.env.EMAIL || \"\";\n const password = options.password || process.env.PASSWORD || \"\";\n\n if (email === \"\" || email === \"dev@example.com\") {\n console.warn(\n `Warning: EMAIL is set to default or missing. ${\n options.email ? \"Override via LoginOptions.email.\" : 'Set EMAIL env var.'\n }`\n );\n }\n if (password === \"\" || password === \"22222222\") {\n console.warn(\n `Warning: PASSWORD is set to default or missing. ${\n options.password ? \"Override via LoginOptions.password.\" : 'Set PASSWORD env var.'\n }`\n );\n }\n}\n\n/** POST JSON payload to a webhook URL with a single internal retry. */\nexport async function sendWebhook(url: string, payload: unknown): Promise<boolean> {\n try {\n await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(10_000),\n });\n return true;\n } catch {\n try {\n await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(10_000),\n });\n return true;\n } catch {\n return false;\n }\n }\n}\n\n/** Serialize Playwright browser-context cookies to a JSON file. */\nexport async function saveCookies(context: BrowserContext, filePath: string): Promise<void> {\n const cookies = await context.cookies();\n const dir = path.dirname(filePath);\n if (dir && !fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(filePath, JSON.stringify(cookies, null, 2), \"utf-8\");\n}\n\n/** Load cookies from a JSON file and add them to a browser context. */\nexport async function loadCookies(\n context: BrowserContext,\n filePath: string\n): Promise<void> {\n if (!fs.existsSync(filePath)) return;\n\n const data = fs.readFileSync(filePath, \"utf-8\");\n const cookies: SerializedCookie[] = JSON.parse(data);\n await context.addCookies(cookies as Parameters<BrowserContext[\"addCookies\"]>[0]);\n}\n\n/** Build Playwright-compatible proxy settings object. */\nexport function setupProxy(proxyConfig?: LoginOptions[\"proxy\"]) {\n if (!proxyConfig) return undefined;\n return {\n server: proxyConfig.server,\n username: proxyConfig.username,\n password: proxyConfig.password,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Core automation\n// ---------------------------------------------------------------------------\n\nexport async function automateLogin(options: LoginOptions): Promise<LoginResult> {\n let browser: Browser | null = null;\n let context: BrowserContext | null = null;\n let page: Page | null = null;\n\n try {\n await validateEnv(options);\n\n const retryCount = options.retryCount ?? 2;\n const baseRetryDelay = options.baseRetryDelay ?? 1000;\n const delayRange = options.delayRange ?? { min: 500, max: 1500 };\n\n // ---- Proxy --------------------------------------------------------\n const proxySettings = setupProxy(options.proxy);\n\n // ---- Launch browser -----------------------------------------------\n const launchOpts: Record<string, unknown> = {\n headless: options.headless ?? false,\n };\n if (proxySettings) {\n launchOpts.proxy = proxySettings;\n }\n\n browser = await chromium.launch(launchOpts);\n\n // ---- Context options ----------------------------------------------\n const contextOptions: Record<string, unknown> = {};\n if (proxySettings && !launchOpts.proxy) {\n contextOptions.proxy = proxySettings;\n }\n\n // Cookie persistence via storageState\n if (options.cookieFile) {\n contextOptions.storageState = options.cookieFile;\n }\n\n // Video recording via context recordVideo option\n if (options.videoPath) {\n const videoDir = path.isAbsolute(options.videoPath)\n ? path.dirname(options.videoPath)\n : path.join(process.cwd(), path.dirname(options.videoPath));\n contextOptions.recordVideo = {\n dir: videoDir,\n size: { width: 1280, height: 720 },\n };\n }\n\n context = await browser.newContext(contextOptions);\n page = await context.newPage();\n\n // ---- Selectors ----------------------------------------------------\n const loginSelector = options.loginSelector || \"#login\";\n const passwordSelector = options.passwordSelector || \"#password\";\n const captchaSelector = \"img.captcha-image\";\n const captchaInputSelector = options.captchaInputSelector || \"#captcha\";\n const submitButtonSelector = options.submitButtonSelector || \"button[type='submit']\";\n\n // ---- Single login attempt -----------------------------------------\n const attemptLogin = async (): Promise<{\n success: true;\n url: string;\n title: string;\n page: Page;\n }> => {\n await executeWithRandomDelay(\n async () =>\n page!.goto(options.url, { waitUntil: \"domcontentloaded\" }),\n ...Object.values(delayRange)\n );\n\n const emailVal = options.email || process.env.EMAIL || \"\";\n const passwordVal = options.password || process.env.PASSWORD || \"\";\n\n await executeWithRandomDelay(\n async () => page!.locator(loginSelector).fill(emailVal),\n ...Object.values(delayRange)\n );\n\n await executeWithRandomDelay(\n async () => page!.locator(passwordSelector).fill(passwordVal),\n ...Object.values(delayRange)\n );\n\n const captchaResult = await solveCaptchaFromPage(\n page!,\n captchaSelector,\n options.outputScreenshotPath ? undefined : undefined\n );\n\n await executeWithRandomDelay(\n async () => page!.locator(captchaInputSelector).fill(captchaResult.text),\n ...Object.values(delayRange)\n );\n\n await executeWithRandomDelay(\n async () => page!.locator(submitButtonSelector).click(),\n ...Object.values(delayRange)\n );\n\n try {\n await page!.waitForLoadState(\"domcontentloaded\", { timeout: 15000 });\n\n if (options.screenshotDelay) {\n await page!.waitForTimeout(options.screenshotDelay);\n }\n\n if (options.outputScreenshotPath) {\n await page!.screenshot({ path: options.outputScreenshotPath, fullPage: true });\n }\n } catch {\n console.warn(\"Warning: Could not wait for post-login state\");\n }\n\n return {\n success: true,\n url: page!.url(),\n title: await page!.title(),\n page: page!,\n };\n };\n\n // ---- Retry loop ---------------------------------------------------\n let result: Awaited<ReturnType<typeof attemptLogin>>;\n\n try {\n result = await retry(attemptLogin, {\n maxAttempts: retryCount + 1, // +1 for the initial attempt\n delayMs: baseRetryDelay,\n multiplier: 2,\n onRetry: (attempt, error, totalDelay) => {\n console.warn(\n `[retry] Attempt ${attempt} failed: ${error instanceof Error ? error.message : error}. Total backoff: ${totalDelay}ms`\n );\n },\n });\n } catch (error) {\n // ---- Failure path -----------------------------------------------\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n let pageTitle = \"\";\n if (page) {\n try {\n pageTitle = await page.title();\n } catch {\n pageTitle = \"failed to get title\";\n }\n }\n\n // Save cookies before leaving (partial session might still be useful)\n if (options.cookieFile && context) {\n try {\n await saveCookies(context, options.cookieFile);\n } catch {\n /* ignore */\n }\n }\n\n // Send failure webhook\n if (options.webhookUrl) {\n await sendWebhook(options.webhookUrl, {\n content: \"🔴 **Login Failed**\",\n embeds: [\n {\n title: \"Login Automation Failed\",\n fields: [\n { name: \"URL\", value: options.url, inline: true },\n {\n name: \"Error\",\n value:\n error instanceof Error ? error.message : String(error),\n inline: false,\n },\n ],\n color: 16734223,\n },\n ],\n });\n }\n\n return {\n success: false,\n url: page?.url() || \"\",\n title: pageTitle,\n page: page!,\n error: errorMessage,\n };\n }\n\n // ---- Success path -------------------------------------------------\n\n // Save cookies after successful login\n if (options.cookieFile && context) {\n try {\n await saveCookies(context, options.cookieFile);\n } catch (err) {\n console.warn(\"Warning: Could not save cookies:\", err);\n }\n }\n\n // Handle video recording — use the context-level recordVideo approach\n if (options.videoPath && page) {\n try {\n const videoObj = page.video();\n if (videoObj) {\n const outputPath = path.isAbsolute(options.videoPath!)\n ? options.videoPath!\n : path.join(process.cwd(), options.videoPath!);\n\n // Wait briefly then save\n await delay(500);\n await videoObj.saveAs(outputPath);\n console.log(`Video saved to ${outputPath}`);\n }\n } catch (err) {\n console.warn(\"Warning: Could not save video recording:\", err);\n }\n }\n\n // Send success webhook\n if (options.webhookUrl) {\n await sendWebhook(options.webhookUrl, {\n content: \"✅ **Login Successful**\",\n embeds: [\n {\n title: \"Login Automation Succeeded\",\n fields: [\n { name: \"URL\", value: options.url, inline: true },\n { name: \"Final URL\", value: result.url, inline: true },\n { name: \"Title\", value: result.title, inline: false },\n ],\n color: 5763719,\n },\n ],\n });\n }\n\n return {\n success: true,\n url: result.url,\n title: result.title,\n page: result.page,\n };\n } catch (error) {\n // Top-level catch for unexpected errors\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n let pageTitle = \"\";\n if (page) {\n try {\n pageTitle = await page.title();\n } catch {\n pageTitle = \"failed to get title\";\n }\n }\n\n // Save cookies on unexpected failure too\n if (options.cookieFile && context) {\n try {\n await saveCookies(context, options.cookieFile);\n } catch {\n /* ignore */\n }\n }\n\n // Send failure webhook\n if (options.webhookUrl) {\n await sendWebhook(options.webhookUrl, {\n content: \"🔴 **Login Error**\",\n embeds: [\n {\n title: \"Unexpected Login Error\",\n fields: [\n { name: \"URL\", value: options.url, inline: true },\n {\n name: \"Error\",\n value: error instanceof Error ? error.message : String(error),\n inline: false,\n },\n ],\n color: 16734223,\n },\n ],\n });\n }\n\n return {\n success: false,\n url: page?.url() || \"\",\n title: pageTitle,\n page: page!,\n error: errorMessage,\n };\n } finally {\n if (browser && !options.headless) {\n await browser.close().catch(() => {});\n }\n }\n}\n","/**\n * Returns a random integer between min and max (inclusive).\n */\nexport function randomBetween(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n/**\n * Delays execution for ms milliseconds with ±20% jitter.\n */\nexport function delay(ms: number): Promise<void> {\n const jittered = ms + Math.floor((Math.random() * 0.4 - 0.2) * ms);\n const actualDelay = Math.max(0, jittered);\n return new Promise((resolve) => setTimeout(resolve, actualDelay));\n}\n\n/**\n * Executes an async action and applies a random delay after it completes.\n * The delay is randomly chosen between minDelay and maxDelay (if provided),\n * defaulting to 500-1500ms.\n */\nexport async function executeWithRandomDelay<T>(\n action: () => Promise<T>,\n minDelay: number = 500,\n maxDelay: number = 1500\n): Promise<T> {\n const result = await action();\n const delayMs = randomBetween(minDelay, maxDelay);\n await delay(delayMs);\n return result;\n}\n","import { solveCaptchaFromPage, SolveCaptchaOptions } from \"./captchaSolve.js\";\nimport {\n automateLogin,\n LoginOptions,\n LoginResult,\n sendWebhook,\n saveCookies,\n loadCookies,\n setupProxy,\n} from \"./login.js\";\nimport {\n randomBetween,\n delay,\n executeWithRandomDelay,\n} from \"./utils/humanDelay.js\";\nimport { retry, isRetryable, RetryOptions, RetryableError } from \"./utils/retry.js\";\n\nexport type { LoginOptions, LoginResult } from \"./login.js\";\nexport type { CaptchaResult } from \"./llm.js\";\nexport type { SolveCaptchaOptions } from \"./captchaSolve.js\";\nexport type { RetryOptions, RetryableError } from \"./utils/retry.js\";\n\nexport { solveCaptchaFromPage };\nexport { automateLogin };\nexport { sendWebhook, saveCookies, loadCookies, setupProxy };\nexport { randomBetween, delay, executeWithRandomDelay };\nexport { retry, isRetryable };\n\nexport default {\n solveCaptchaFromPage,\n automateLogin,\n sendWebhook,\n saveCookies,\n loadCookies,\n setupProxy,\n randomBetween,\n delay,\n executeWithRandomDelay,\n retry,\n isRetryable,\n};\n"],"mappings":"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","names":["config"]}
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1,11 +1,29 @@
|
|
|
1
|
-
import { Page } from 'playwright';
|
|
1
|
+
import { Page, BrowserContext } from 'playwright';
|
|
2
2
|
|
|
3
|
+
// ----- CaptchaResult (LLM) -----
|
|
3
4
|
export interface CaptchaResult {
|
|
4
5
|
text: string;
|
|
5
6
|
description: string;
|
|
6
7
|
}
|
|
7
8
|
|
|
9
|
+
// ----- SolveCaptchaOptions -----
|
|
10
|
+
export interface SolveCaptchaOptions {
|
|
11
|
+
maxRetries?: number;
|
|
12
|
+
retryDelayMs?: number;
|
|
13
|
+
retryMultiplier?: number;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// ----- Proxy -----
|
|
18
|
+
export interface ProxyConfig {
|
|
19
|
+
server: string;
|
|
20
|
+
username?: string;
|
|
21
|
+
password?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ----- Login -----
|
|
8
25
|
export interface LoginOptions {
|
|
26
|
+
// Existing
|
|
9
27
|
url: string;
|
|
10
28
|
loginSelector?: string;
|
|
11
29
|
passwordSelector?: string;
|
|
@@ -14,6 +32,29 @@ export interface LoginOptions {
|
|
|
14
32
|
headless?: boolean;
|
|
15
33
|
outputScreenshotPath?: string;
|
|
16
34
|
screenshotDelay?: number;
|
|
35
|
+
|
|
36
|
+
// New – credentials override
|
|
37
|
+
email?: string;
|
|
38
|
+
password?: string;
|
|
39
|
+
|
|
40
|
+
// New – retry
|
|
41
|
+
retryCount?: number;
|
|
42
|
+
baseRetryDelay?: number;
|
|
43
|
+
|
|
44
|
+
// New – human-like timing
|
|
45
|
+
delayRange?: { min: number; max: number };
|
|
46
|
+
|
|
47
|
+
// New – proxy
|
|
48
|
+
proxy?: ProxyConfig;
|
|
49
|
+
|
|
50
|
+
// New – session persistence
|
|
51
|
+
cookieFile?: string;
|
|
52
|
+
|
|
53
|
+
// New – video recording
|
|
54
|
+
videoPath?: string;
|
|
55
|
+
|
|
56
|
+
// New – webhook notifications
|
|
57
|
+
webhookUrl?: string;
|
|
17
58
|
}
|
|
18
59
|
|
|
19
60
|
export interface LoginResult {
|
|
@@ -24,10 +65,42 @@ export interface LoginResult {
|
|
|
24
65
|
error?: string;
|
|
25
66
|
}
|
|
26
67
|
|
|
68
|
+
// ----- Human Delay utilities -----
|
|
69
|
+
export declare function randomBetween(min: number, max: number): number;
|
|
70
|
+
export declare function delay(ms: number): Promise<void>;
|
|
71
|
+
export declare function executeWithRandomDelay<T>(
|
|
72
|
+
action: () => Promise<T>,
|
|
73
|
+
minDelay?: number,
|
|
74
|
+
maxDelay?: number
|
|
75
|
+
): Promise<T>;
|
|
76
|
+
|
|
77
|
+
// ----- Retry utilities -----
|
|
78
|
+
export declare function retry<T>(
|
|
79
|
+
fn: () => Promise<T>,
|
|
80
|
+
options?: RetryOptions
|
|
81
|
+
): Promise<T>;
|
|
82
|
+
export declare function isRetryable(error: unknown): boolean;
|
|
83
|
+
|
|
84
|
+
export interface RetryOptions {
|
|
85
|
+
maxAttempts?: number;
|
|
86
|
+
delayMs?: number;
|
|
87
|
+
multiplier?: number;
|
|
88
|
+
onRetry?: (attempt: number, error: unknown, totalDelay: number) => void;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ----- Helper functions -----
|
|
92
|
+
export declare function sendWebhook(url: string, payload: unknown): Promise<boolean>;
|
|
93
|
+
export declare function saveCookies(context: BrowserContext, filePath: string): Promise<void>;
|
|
94
|
+
export declare function loadCookies(context: BrowserContext, filePath: string): Promise<void>;
|
|
95
|
+
import type { ProxySettings } from 'playwright';
|
|
96
|
+
export declare function setupProxy(proxyConfig?: ProxyConfig): ProxySettings | undefined;
|
|
97
|
+
|
|
98
|
+
// ----- Signatures -----
|
|
27
99
|
declare function solveCaptchaFromPage(
|
|
28
100
|
page: Page,
|
|
29
101
|
captchaSelector?: string,
|
|
30
|
-
outputScreenshotPath?: string
|
|
102
|
+
outputScreenshotPath?: string,
|
|
103
|
+
options?: SolveCaptchaOptions
|
|
31
104
|
): Promise<CaptchaResult>;
|
|
32
105
|
|
|
33
106
|
declare function automateLogin(options: LoginOptions): Promise<LoginResult>;
|
|
@@ -35,6 +108,15 @@ declare function automateLogin(options: LoginOptions): Promise<LoginResult>;
|
|
|
35
108
|
declare const _default: {
|
|
36
109
|
solveCaptchaFromPage: typeof solveCaptchaFromPage;
|
|
37
110
|
automateLogin: typeof automateLogin;
|
|
111
|
+
sendWebhook: typeof sendWebhook;
|
|
112
|
+
saveCookies: typeof saveCookies;
|
|
113
|
+
loadCookies: typeof loadCookies;
|
|
114
|
+
setupProxy: typeof setupProxy;
|
|
115
|
+
randomBetween: typeof randomBetween;
|
|
116
|
+
delay: typeof delay;
|
|
117
|
+
executeWithRandomDelay: typeof executeWithRandomDelay;
|
|
118
|
+
retry: typeof retry;
|
|
119
|
+
isRetryable: typeof isRetryable;
|
|
38
120
|
};
|
|
39
121
|
|
|
40
122
|
export { solveCaptchaFromPage };
|