diff --git a/package.json b/package.json index 6ea757a..17f3fcc 100644 --- a/package.json +++ b/package.json @@ -220,6 +220,7 @@ "docs:preview": "cd docs && bun run preview", "widget:build": "cd widget && bun run build.js", "widget:publish": "cd widget && cd src && sudo npm publish --access public", - "server:publish": "cd server && sudo npm publish --access public" + "server:publish": "cd server && sudo npm publish --access public", + "cli:publish": "cd solver-cli && sudo npm publish --access public" } } diff --git a/solver-cli/.gitignore b/solver-cli/.gitignore new file mode 100644 index 0000000..a14702c --- /dev/null +++ b/solver-cli/.gitignore @@ -0,0 +1,34 @@ +# dependencies (bun install) +node_modules + +# output +out +dist +*.tgz + +# code coverage +coverage +*.lcov + +# logs +logs +_.log +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# caches +.eslintcache +.cache +*.tsbuildinfo + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/solver-cli/README.md b/solver-cli/README.md new file mode 100644 index 0000000..65bbec4 --- /dev/null +++ b/solver-cli/README.md @@ -0,0 +1,15 @@ +# solver-cli + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run index.js +``` + +This project was created using `bun init` in bun v1.2.10. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/solver-cli/bun.lock b/solver-cli/bun.lock new file mode 100644 index 0000000..519337a --- /dev/null +++ b/solver-cli/bun.lock @@ -0,0 +1,30 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "solver-cli", + "dependencies": { + "@cap.js/solver": "^0.0.3", + }, + "devDependencies": { + "@types/bun": "latest", + }, + "peerDependencies": { + "typescript": "^5", + }, + }, + }, + "packages": { + "@cap.js/solver": ["@cap.js/solver@0.0.3", "", {}, "sha512-J/Vso8LllJGBmVuj68mXalSsOg8a+Ry0/lnOYu63srk37UFlbQVWdcm63hARnEdOduR33DWS0Ot/yGHPliJhqw=="], + + "@types/bun": ["@types/bun@1.2.10", "", { "dependencies": { "bun-types": "1.2.10" } }, "sha512-eilv6WFM3M0c9ztJt7/g80BDusK98z/FrFwseZgT4bXCq2vPhXD4z8R3oddmAn+R/Nmz9vBn4kweJKmGTZj+lg=="], + + "@types/node": ["@types/node@22.14.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw=="], + + "bun-types": ["bun-types@1.2.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-b5ITZMnVdf3m1gMvJHG+gIfeJHiQPJak0f7925Hxu6ZN5VKA8AGy4GZ4lM+Xkn6jtWxg5S3ldWvfmXdvnkp3GQ=="], + + "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + } +} diff --git a/solver-cli/index.js b/solver-cli/index.js new file mode 100644 index 0000000..a39b6d5 --- /dev/null +++ b/solver-cli/index.js @@ -0,0 +1,51 @@ +#!/usr/bin/env bun + +import solver from "@cap.js/solver"; +import kleur from "kleur"; + +const args = process.argv.slice(2); + +(async () => { + if (args.length === 0) { + console.log(`\n${kleur.cyan("@cap.js/cli")} ${kleur.gray( + "cli solver for cap challenges" + )} + +Usage: + ${kleur.dim("$")} bunx ${kleur.bold("@cap.js/cli")} + +Options: + The challenges to solve in + format \`salt:target\``); + return; + } + + const challenges = args.map((arg) => { + const [salt, target] = arg.split(":"); + + if (!salt || !target) { + console.error( + `${kleur.red("Error:")} ${kleur.yellow(arg)} is not a valid challenge` + ); + process.exit(1); + } + + return [salt, target]; + }); + + console.log(`\n${kleur.cyan("@cap.js/cli")} ${kleur.dim(`${challenges.length} challenges`)}\n\n\n`); + + const solutions = await solver(challenges, { + onProgress: (status) => { + process.stdout.moveCursor(0, -2); + process.stdout.clearScreenDown(); + console.log( + `${status.result.salt}:${status.result.target}:${status.result.nonce}` + ); + console.log(kleur.dim("\nSolving challenges… " + status.progress + "%")); + }, + }); + + process.stdout.moveCursor(0, -2); + process.stdout.clearScreenDown(); +})(); \ No newline at end of file diff --git a/solver-cli/package.json b/solver-cli/package.json new file mode 100644 index 0000000..52525bd --- /dev/null +++ b/solver-cli/package.json @@ -0,0 +1,18 @@ +{ + "name": "@cap.js/cli", + "module": "index.js", + "type": "module", + "private": false, + "devDependencies": { + "@types/bun": "latest" + }, + "peerDependencies": { + "typescript": "^5" + }, + "dependencies": { + "@cap.js/solver": "^0.0.3" + }, + "bin": { + "cli": "./index.js" + } +} diff --git a/solver/example.js b/solver/example.js index c6f707b..a6326d2 100644 --- a/solver/example.js +++ b/solver/example.js @@ -21,4 +21,15 @@ const CHALLENGES = [ ["0c21ade6e63a4e37b13cb8b087f31863", "65c9"], ]; -console.log(await solver(CHALLENGES)); +const solutions = await solver(CHALLENGES, { + onProgress: (status) => { + process.stdout.moveCursor(0, -1); + process.stdout.clearScreenDown(); + console.log(`Progress: ${status.progress}%`); + }, +}); + +process.stdout.moveCursor(0, -1); +process.stdout.clearScreenDown(); + +console.log("Solutions:", solutions); \ No newline at end of file diff --git a/solver/index.js b/solver/index.js index 7d8f160..7af072c 100644 --- a/solver/index.js +++ b/solver/index.js @@ -72,6 +72,15 @@ export default function solver(challenges, config) { challengesProcessed++; activeWorkers--; + if (config?.onProgress) { + config.onProgress({ + progress: Math.floor((challengesProcessed / totalChallenges) * 100), + currentChallenge: currentChallengeIndex, + challengesProcessed, + result, + }); + } + if (challengesProcessed === totalChallenges) { resolve(results); } else { diff --git a/solver/package.json b/solver/package.json index 55a3ff5..a6560d1 100644 --- a/solver/package.json +++ b/solver/package.json @@ -1,6 +1,6 @@ { "name": "@cap.js/solver", - "version": "0.0.2", + "version": "0.0.3", "description": "Server-side solver for Cap's SHA-256 PoW captchas. Cap is a lightweight, modern open-source CAPTCHA alternative designed using SHA-256 PoW.", "main": "index.js", "scripts": {