Thank you for your interest in improving this educational project! We welcome contributions, especially adding support for planned games or refining existing level handlers.
Please note that this project is strictly for educational purposes to demonstrate browser automation, frontend frameworks, and classic computer science algorithms.
The iam_not_a_robot/ workspace uses a modular registry system. When a new level is encountered, the state machine reads the DOM title and executes the matched handler inside src/not-a-robot/handlers.ts.
When writing or updating a level solver, always attempt to build out the solution in this specific order of operations:
- Method 1 (Vue State Mutation): Try querying the
.__vue__instance property on the component container and updating its structural$datafields directly. - Method 2 (Authentic DOM Playback): If the data engine is locked down or validated externally, fall back to triggering mechanical actions like
.click(), keyboard actions, or.dispatchEvent(new DragEvent(...)). - Method 3 (Lifecycle Hook Override): If the puzzle is mathematically impossible or computationally excessive to simulate within standard timeouts, intercept and rewrite the internal component
verify()or validation method natively inside the browser context.
To register a new level, open src/not-a-robot/handlers.ts and add your code to the handler system:
import { Page } from '@playwright/test';
import { logger } from './logger';
/**
* Example level handler implementation
* @param page The active Playwright page instance
*/
export async function solveLevelX(page: Page): Promise<void> {
logger.info('Executing solver for Level X...');
// Step 1: Execute scripts safely within the browser frame context
await page.evaluate(() => {
const container = document.querySelector('.page-container');
if (container && (container as any).__vue__) {
const vm = (container as any).__vue__;
// Implement Method 1 or Method 3 here
if (vm.$data) {
vm.$data.isSolved = true;
}
}
});
// Step 2: Fall back to direct DOM clicking if mutation is insufficient
const verifyButton = page.locator('button:has-text("Verify")');
await verifyButton.click();
}
// Remember to append your solver reference to the LEVEL_HANDLERS map object at the bottom of the file!- Fork the repo and clone it locally.
- Ensure you have Node.js 20+ and your choice of package manager installed (
pnpmpreferred). - Run
pnpm installto load typing definitions and dependencies. - Run
pnpm exec playwright install chromiumto fetch the browser binaries. - Create a cleanly named feature branch (e.g.,
feat/level-40-handler).
- Always add accompanying unit tests to
tests/xoxo.test.tsor respective test suites if writing complex mathematical heuristics. - Ensure all structural application runtime processes use the Winston
loggerrather than basicconsole.log()outputs. - Make sure your complete automated pipeline runs successfully locally by asserting
npm testorpnpm testclears without errors before submitting a Pull Request.