From 74799c43663c0ed1d2c44c73b39912d3696f42a1 Mon Sep 17 00:00:00 2001 From: Furry Date: Thu, 28 Mar 2024 11:21:55 -0500 Subject: [PATCH] Staging for NPM publish --- .gitignore | 3 +- .npmignore | 10 +++ package.json | 2 +- readme.md | 112 ++++++++++++++++++++++++++++--- src/structs/solver.ts | 11 ++- test/InteractiveCaptchas.test.js | 78 +++++++++++++++++++-- test/funcaptcha.test.js | 12 ---- test/geetest.test.js | 41 ----------- test/hcaptcha.test.js | 24 ------- test/imageCaptcha.test.js | 28 -------- test/manual/v2test.js | 13 +--- test/manual/viewPending.js | 30 --------- test/multi.test.js | 15 ----- test/recaptcha.test.js | 35 ---------- test/turnstile.test.js | 26 ------- tests.spec.js | 0 16 files changed, 198 insertions(+), 242 deletions(-) create mode 100644 .npmignore delete mode 100644 test/funcaptcha.test.js delete mode 100644 test/geetest.test.js delete mode 100644 test/hcaptcha.test.js delete mode 100644 test/imageCaptcha.test.js delete mode 100644 test/manual/viewPending.js delete mode 100644 test/multi.test.js delete mode 100644 test/recaptcha.test.js delete mode 100644 test/turnstile.test.js delete mode 100644 tests.spec.js diff --git a/.gitignore b/.gitignore index 4864136..e621aae 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ dist/ # Files yarn.lock -.env \ No newline at end of file +.env +package-lock.json \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..2f8f517 --- /dev/null +++ b/.npmignore @@ -0,0 +1,10 @@ +# Folders +node_modules/ +src/ +test/ + +# Files +.env +.gitignore +package-lock.json +yarn.lock \ No newline at end of file diff --git a/package.json b/package.json index 76731a6..5167c16 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "2captcha", - "version": "3.0.0@next", + "version": "4.0.0@next", "description": "An asynchronous wrapper around the 2captcha API.", "main": "dist/index.js", "repository": "https://github.com/furry/2captcha", diff --git a/readme.md b/readme.md index 8f2f502..f3f29a1 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -
+

2captcha

@@ -12,18 +12,108 @@ ![Size](https://img.shields.io/bundlephobia/min/2captcha) ![Downloads](https://img.shields.io/npm/dw/2captcha) -
+ + +
A wrapper around the 2captcha API
+ +
-

A wrapper around the 2captcha API

+## Motive + +2captcha is a service that solves many different types of captchas, this library serves as a wrapper around their API to bring easy, promise-based functionality to NodeJS. This libary specilizes in concurrent solves, and bulk-api usage. ## Features - - Strict typings & full TS/JS support - - Single-Request polling - - Promise based solves - - EventEmitter Support - - Account Endpoints - - Pingback Support - - Browser / Node - - Proxy Support +- Promise based 2captcha solving +- Browser & NodeJS Support +- Uses node-fetch, a light weight http library +- Fluent typings & TS support +- Account Interaction +- Invalid Captcha reporting +- Proxy Support + +## Planned Features + +- Pingback / Webhook support via express + +## Install + +```sh +npm install 2captcha@next +``` +```sh +yarn add 2captcha@next +``` + +## Usage + + +Recaptcha, +```js +const Captcha = require("2captcha") + +// A new 'solver' instance with our API key +const solver = new Captcha.Solver("") +/* Example ReCaptcha Website */ +solver.recaptchaV2("6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5", "https://patrickhlauke.github.io/recaptcha/") +.then((res) => { + console.log(res) +}) +.catch((err) => { + console.error(err.message) +}) +``` + +Image, +```js +const Captcha = require("2captcha") +const fs = require("fs") + +const solver = new Captcha.Solver("") + +// Read from a file as base64 text +solver.imageCaptcha(fs.readFileSync("./captcha.png", "base64")) +.then((res) => { + // Logs the image text + console.log(res) +}) +.catch((err) => { + console.error(err.message) +}) +``` + +Proxy, +```js +const Captcha = require("2captcha") + +const solver = new Captcha.Solver("") + + +solver.recaptchaV2("6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5", "https://patrickhlauke.github.io/recaptcha/", true /* for proxied */, false /* not enterprise */, { + proxy: "21.214.43.26", // The (Username : Password @ Address) of our chosen proxy + proxyType: "HTTP", // The 'Type' of proxy, http, https, socks, ect. + proxyLogin: "username", + proxyPassword: "password123" +}) +.then((res) => { + console.log(res) +}) +.catch((err) => { + console.error(err.message) +}) +``` + +## Commit Guidelines + +The latest version of the code base will always be under the '**next**' branch! + +- All pull requiests must provide a valid reason for the change or implementation +- All **CORE CHANGES** require an issue with reasoning made before a PR will even be addressed. +- All PR's must follow the general structure of the code base +- If you have questions, feel free to make an issue and i'll get to it right away! + +
+
+Buy Me A Coffee +
diff --git a/src/structs/solver.ts b/src/structs/solver.ts index 20ab243..7dfc739 100644 --- a/src/structs/solver.ts +++ b/src/structs/solver.ts @@ -7,7 +7,6 @@ import { CloudflareTurnstile, CoordinateCaptchaResult, CoordinatesTaskExtras, - CreatedTaskResponse, DataDomeCaptchaResult, DataDomeExtras, DrawAroundResult, @@ -156,7 +155,13 @@ export class Solver { throw new NetError(err, this._locale); }) - const json = await response.json(); + let json; + try { + json = await response.json(); + } catch (e) { + let t = await response.text() + throw new NetError("UnexpectedHTMLResponse", this._locale); + } if (json.errorId == 0) { return json.taskId; @@ -202,7 +207,7 @@ export class Solver { * @param captchaId The captcha ID to get the solution of. * @returns The resulting captcha promise. */ - private async registerPollEntry(task: number, delay = 5000): Promise> { + protected async registerPollEntry(task: number, delay = 5000): Promise> { const captchaPromiseObject: PendingCaptchaStorage = { startTime: Date.now(), captchaId: task, diff --git a/test/InteractiveCaptchas.test.js b/test/InteractiveCaptchas.test.js index 1505555..ce43f8d 100644 --- a/test/InteractiveCaptchas.test.js +++ b/test/InteractiveCaptchas.test.js @@ -2,17 +2,19 @@ import * as Captcha from "../dist/index.js"; import dotenv from "dotenv"; import fs from "fs"; import chai from "chai"; +import { it } from "mocha"; const { expect } = chai; describe("Recaptcha Test", () => { + dotenv.config(); const solver = new Captcha.Solver(process.env.TOKEN); it("Should return a solve for the recaptcha", async () => { - // Using https://patrickhlauke.github.io/recaptcha/ for v2 const result = await solver.recaptchaV2("6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5", "https://patrickhlauke.github.io/recaptcha/"); - expect(result.solution.gRecaptchaResponse).to.greaterThan(256); + expect(result.solution.gRecaptchaResponse.length).to.be.greaterThan(64); + expect(result.solution.token.length).to.be.greaterThan(64); }); it("Should error for invalid key", async () => { @@ -27,7 +29,75 @@ describe("Recaptcha Test", () => { try { await solver.recaptchaV2("6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5", "https://example.com/"); } catch (e) { - expect(e.message).to.equal("ERROR_CAPTCHA_UNSOLVABLE"); + expect(e.code).to.equal("ERROR_CAPTCHA_UNSOLVABLE"); } }) -}) \ No newline at end of file +}) + +describe("hCaptcha Test", () => { + const solver = new Captcha.Solver(process.env.TOKEN); + + it("Should return a solve", async () => { + const response = await solver.hcaptcha("e1715201-770b-4f61-87da-523133844aec", "https://vastus.github.io/login"); + expect(response.solution.token.length).to.be.greaterThan(64); + }) + + it("Should error for invalid key", async () => { + try { + await solver.hcaptcha("Invalid Key", "https://vastus.github.io/login"); + } catch (e) { + expect(e.code).to.equal("ERROR_BAD_PARAMETERS"); + } + }) +}) + +describe("Lemin Test", async () => { + dotenv.config(); + const solver = new Captcha.Solver(process.env.TOKEN); + + it("Should return a solve", async () => { + // const response = await solver.leminPuzzle("https://2captcha.com/demo/lemin", "CROPPED_3dfdd5c_d1872b526b794d83ba3b365eb15a200b", "lemin-cropped-captcha"); + const response = await solver.leminPuzzle("https://2captcha.com/demo/lemin", "CROPPED_3dfdd5c_d1872b526b794d83ba3b365eb15a200b", "lemin-cropped-captcha") + + expect(response.solution.answer.length).to.be.greaterThan(64); + expect(response.solution.challenge_id.length).to.be.greaterThan(10); + }) + + it("Should error for invalid key", async () => { + try { + await solver.leminPuzzle("https://2captcha.com/demo/lemin", "CROPPED_3dfdd5c_d1872b526b794d83ba3b365eb15a200bawdaawdad", "lemin-cropped-captcha", false); + } catch (e) { + expect(["ERROR_KEY_DOES_NOT_EXIST", "ERROR_CAPTCHA_UNSOLVABLE"]).to.include(e.code); + } + }) +}) + +describe("KeyCaptcha Test", () => { + dotenv.config(); + const solver = new Captcha.Solver(process.env.TOKEN) + + it("Should return a solve", async () => { + const response = await solver.keycaptcha(false, { + s_s_c_user_id: 184015, + s_s_c_session_id: "9ff29e0176e78eb7ba59314f92dbac1b", + s_s_c_web_server_sign: "964635241a3e5e76980f2572e5f63452", + s_s_c_web_server_sign2: "3ca802a38ffc5831fa293ac2819b1204", + websiteURL: "https://2captcha.com/demo/keycaptcha" + }) + + expect(response.solution.token.length).to.be.greaterThan(64); + }) +}) + +describe("MtCaptcha Test", () => { + dotenv.config(); + const solver = new Captcha.Solver(process.env.TOKEN); + + it("Should return a solve", async () => { + const response = await solver.mtCaptcha("https://2captcha.com/demo/mtcaptcha", "MTPublic-KzqLY1cKH"); + + expect(response.solution.answer.length).to.be.greaterThan(64); + }) +}) + + diff --git a/test/funcaptcha.test.js b/test/funcaptcha.test.js deleted file mode 100644 index 9da521c..0000000 --- a/test/funcaptcha.test.js +++ /dev/null @@ -1,12 +0,0 @@ -import * as Captcha from "../dist/index.js"; -import dotenv from "dotenv"; -import fs from "fs"; -import chai from "chai"; - -const { expect } = chai; - -dotenv.config(); - -describe("Funcaptcha Test", () => { - const solver = new Captcha.Solver(process.env.TOKEN); -}); \ No newline at end of file diff --git a/test/geetest.test.js b/test/geetest.test.js deleted file mode 100644 index c5189e2..0000000 --- a/test/geetest.test.js +++ /dev/null @@ -1,41 +0,0 @@ -import * as Captcha from "../dist/index.js"; -import dotenv from "dotenv"; -import fs from "fs"; -import chai from "chai"; -import fetch from "node-fetch"; - -const { expect } = chai; - -dotenv.config(); - - - -function createUUID() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = Math.random() * 16 | 0; - var v = c === 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); -} - -// (async () => { -// const solver = new Captcha.Solver(process.env.TOKEN); - -// const data = await fetch("https://2captcha.com/demo/geetest").then((res) => res.json()); - -// // Using geetest's official demo (https://geetest.com/en/demo) -// const result = await solver.geetest(data.gt, data.challenge, "https://2captcha.com/demo/geetest") -// console.log(result); -// // const result = await solver.geetestv4("050cffef4ae57b5d5e529fea9540b0d1", "https://www.geetest.com/en/demo"); -// })() - -// describe("geetest", async () => { -// const solver = new Captcha.Solver(process.env.TOKEN); - -// // Using geetest's official demo (https://geetest.com/en/demo) -// const result = await solver.geetestv4("050cffef4ae57b5d5e529fea9540b0d1", "https://www.geetest.com/en/demo"); - -// console.log(result); - -// // solver.geetest(createUUID(), ) -// }); \ No newline at end of file diff --git a/test/hcaptcha.test.js b/test/hcaptcha.test.js deleted file mode 100644 index 5747b6d..0000000 --- a/test/hcaptcha.test.js +++ /dev/null @@ -1,24 +0,0 @@ -import * as Captcha from "../dist/index.js"; -import dotenv from "dotenv"; -import chai from "chai"; - -const { expect } = chai; - -dotenv.config(); - -describe("hCaptcha Test", () => { - const solver = new Captcha.Solver(process.env.TOKEN); - it("Should return a solve for the hcaptcha", async () => { - // Using https://vastus.github.io/login for HCaptcha - const captcha = await solver.hcaptcha("e1715201-770b-4f61-87da-523133844aec", "https://vastus.github.io/login"); - expect(captcha.data.respKey.length).to.greaterThan(256); - }); - - it("Should error for invalid key", async () => { - try { - await solver.hcaptcha("Invalid Key", "https://vastus.github.io/login"); - } catch (e) { - expect(e.message).to.equal("ERROR_SITEKEY"); - } - }); -}); \ No newline at end of file diff --git a/test/imageCaptcha.test.js b/test/imageCaptcha.test.js deleted file mode 100644 index cf59404..0000000 --- a/test/imageCaptcha.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import * as Captcha from "../dist/index.js"; -import dotenv from "dotenv"; -import fs from "fs"; -import chai from "chai"; - -const { expect } = chai; - -dotenv.config(); - -describe("Image Captcha Test", () => { - it("Should return a captcha with the characters '263S2V'", async () => { - const solver = new Captcha.Solver(process.env.TOKEN); - - // Read the image as a base64 string from "./resources/testImage.png" - const b64Image = fs.readFileSync("./test/resources/testImage.png", "base64"); - const bufferImage = Buffer.from(b64Image, "base64"); - - const results = await Promise.all([ - // Attempt with both base64 and a buffer. - solver.imageCaptcha(bufferImage), - solver.imageCaptcha(b64Image), - ]); - - expect( - results.filter(x => x.data == "263S2V").length - ).to.be.greaterThan(0); - }); -}) \ No newline at end of file diff --git a/test/manual/v2test.js b/test/manual/v2test.js index 9670bb3..7774177 100644 --- a/test/manual/v2test.js +++ b/test/manual/v2test.js @@ -5,15 +5,6 @@ import chai from "chai"; dotenv.config(); -(async () => { - const solver = new Captcha.Solver(process.env.TOKEN); - - try { - await solver.recaptchaV2("Invalid Key", "https://patrickhlauke.github.io/recaptcha/"); - } catch (e) { - console.log(e) - // expect(e.message).to.equal("ERROR_WRONG_GOOGLEKEY"); - } - - // console.log(result) +(async () => { + })() \ No newline at end of file diff --git a/test/manual/viewPending.js b/test/manual/viewPending.js deleted file mode 100644 index 1043b8b..0000000 --- a/test/manual/viewPending.js +++ /dev/null @@ -1,30 +0,0 @@ -import * as Captcha from "../../dist/index.js"; -import dotenv from "dotenv"; -import fs from "fs"; -import chai from "chai"; - -const { expect } = chai; - -dotenv.config(); - -(async () => { - const solver = new Captcha.Solver(process.env.TOKEN); - - setInterval(() => { - console.log(solver.getPending()); - }, 500); - - // import the image from "../resources/testImage.png" - const b64Image = fs.readFileSync("./test/resources/testImage.png", "base64"); - - const cache = []; - // for loop with 5 elements - for (let i = 0; i < 5; i++) { - cache.push( - solver.imageCaptcha(b64Image) - ); - } - - await Promise.all(cache); - process.exit(); -})(); \ No newline at end of file diff --git a/test/multi.test.js b/test/multi.test.js deleted file mode 100644 index 6e376d3..0000000 --- a/test/multi.test.js +++ /dev/null @@ -1,15 +0,0 @@ -import * as Captcha from "../dist/index.js"; -import dotenv from "dotenv"; -import fs from "fs"; -import chai from "chai"; - -const { expect } = chai; - -dotenv.config(); - -describe("Multi Image Test", () => { - const solver = new Captcha.Solver(process.env.TOKEN); - it("Should solve multiple image captchas.", async () => { - solver - }) -}) \ No newline at end of file diff --git a/test/recaptcha.test.js b/test/recaptcha.test.js deleted file mode 100644 index d2ac816..0000000 --- a/test/recaptcha.test.js +++ /dev/null @@ -1,35 +0,0 @@ -import * as Captcha from "../dist/index.js"; -import dotenv from "dotenv"; -import fs from "fs"; -import chai from "chai"; - -const { expect } = chai; - -dotenv.config(); - -describe("Recaptcha Test", () => { - const solver = new Captcha.Solver(process.env.TOKEN); - it("Should return a solve for the recaptcha", async () => { - - // Using https://patrickhlauke.github.io/recaptcha/ for v2 - const captcha = await solver.recaptchaV2("6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5", "https://patrickhlauke.github.io/recaptcha/"); - - expect(captcha.data.length).to.greaterThan(256); - }); - - it("Should error for invalid key", async () => { - try { - await solver.recaptchaV2("Invalid Key", "https://patrickhlauke.github.io/recaptcha/"); - } catch (e) { - expect(e.message).to.equal("ERROR_WRONG_GOOGLEKEY"); - } - }); - - it("Should error for invalid url", async () => { - try { - await solver.recaptchaV2("6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5", "https://example.com/"); - } catch (e) { - expect(e.message).to.equal("ERROR_CAPTCHA_UNSOLVABLE"); - } - }) -}) \ No newline at end of file diff --git a/test/turnstile.test.js b/test/turnstile.test.js deleted file mode 100644 index 842331c..0000000 --- a/test/turnstile.test.js +++ /dev/null @@ -1,26 +0,0 @@ -import * as Captcha from "../dist/index.js"; -import dotenv from "dotenv"; -import fs from "fs"; -import chai from "chai"; - -const { expect } = chai; - -dotenv.config(); - -// describe("Image Captcha Test", () => { -// it("Should return a captcha with the characters '263S2V'", async () => { -// const solver = new Captcha.Solver(process.env.TOKEN); - -// const result = await solver.turnstile("0x4AAAAAAAC3DHQFLr1GavRN"); - -// console.log(result) -// }); -// }) - -// (async () => { -// const solver = new Captcha.Solver(process.env.TOKEN); - -// const result = await solver.turnstile("0x4AAAAAAAC3DHQFLr1GavRN"); - -// console.log(result) -// })() \ No newline at end of file diff --git a/tests.spec.js b/tests.spec.js deleted file mode 100644 index e69de29..0000000