diff --git a/README.md b/README.md index 37ab0ed..c9ea2ea 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ Examples of API requests for different captcha types are available on the [JavaS - [TSPD](#tspd) - [Basilisk](#basilisk) - [Hunt](#hunt) + - [Drag and Drop](#drag-and-drop) - [Other methods](#other-methods) - [goodReport](#goodreport) - [badReport](#badreport) @@ -955,6 +956,30 @@ console.log(err); }) ``` +### Drag and Drop + +[API method description.](https://2captcha.com/2captcha-api#drag-and-drop-captcha) + +A method for solving captcha where one or more images need to be dragged onto specific positions on a background image. + +Required parameters: `body`, `images`. + +The result (`data`) is a pipe-separated string of coordinates, for example `"120,340|null|210,90"`. The order matches the order of the `images` array you sent. `null` means the corresponding image wasn't moved — it does **not** mean an error or coordinates `(0,0)`. + +```js +solver.dragAndDrop({ + body: "BASE64_BACKGROUND_IMAGE", + images: ["BASE64_IMAGE_1", "BASE64_IMAGE_2"], + textinstructions: "Drag the images to proper position" +}) +.then((res) => { +console.log(res); +}) +.catch((err) => { +console.log(err); +}) +``` + ## Other methods ### goodReport diff --git a/examples/dragAndDrop.js b/examples/dragAndDrop.js new file mode 100644 index 0000000..2240427 --- /dev/null +++ b/examples/dragAndDrop.js @@ -0,0 +1,23 @@ +const fs = require('fs'); +const TwoCaptcha = require("../dist/index.js"); +require('dotenv').config(); +const APIKEY = process.env.APIKEY; +const solver = new TwoCaptcha.Solver(APIKEY); + +const backgroundBase64 = fs.readFileSync("./media/drag_drop_main.jpeg", "base64") +const imagesBase64 = [ + fs.readFileSync("./media/drag_drop_image1.jpeg", "base64"), + fs.readFileSync("./media/drag_drop_image2.jpeg", "base64") +] + +solver.dragAndDrop({ + body: backgroundBase64, + images: imagesBase64, + textinstructions: "Drag the images to proper position" +}) +.then((res) => { + console.log(res); +}) +.catch((err) => { + console.log(err); +}) diff --git a/examples/media/drag_drop_image1.jpeg b/examples/media/drag_drop_image1.jpeg new file mode 100644 index 0000000..f1bb604 Binary files /dev/null and b/examples/media/drag_drop_image1.jpeg differ diff --git a/examples/media/drag_drop_image2.jpeg b/examples/media/drag_drop_image2.jpeg new file mode 100644 index 0000000..86ed7a8 Binary files /dev/null and b/examples/media/drag_drop_image2.jpeg differ diff --git a/examples/media/drag_drop_main.jpeg b/examples/media/drag_drop_main.jpeg new file mode 100644 index 0000000..675ba0d Binary files /dev/null and b/examples/media/drag_drop_main.jpeg differ diff --git a/package-lock.json b/package-lock.json index 7900474..5de7324 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@2captcha/captcha-solver", - "version": "1.3.5", + "version": "1.3.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@2captcha/captcha-solver", - "version": "1.3.5", + "version": "1.3.8", "license": "MIT", "dependencies": { "node-fetch": "^2.6.1" diff --git a/package.json b/package.json index fba3aa1..530b4f3 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,8 @@ "Alibaba Captcha", "TSPD", "Basilisk", - "Hunt" + "Hunt", + "Drag and Drop" ], "scripts": { "build": "tsc && node ./dist/index.js", diff --git a/src/structs/2captcha.ts b/src/structs/2captcha.ts index ae89411..e42bccb 100644 --- a/src/structs/2captcha.ts +++ b/src/structs/2captcha.ts @@ -379,6 +379,15 @@ export interface paramsHunt { proxytype?: string, } +export interface paramsDragAndDrop { + body: string, + images: string[], + textinstructions?: string, + language?: 0 | 1 | 2, + lang?: string, + pingback?: string, +} + /** * An object containing properties of the captcha solution. * @typedef {Object} CaptchaAnswer @@ -2739,6 +2748,72 @@ public async hunt(params: paramsHunt): Promise { } } +/** + * ### Solves Drag & Drop captcha + * + * A method for solving captcha where one or more images need to be dragged onto specific positions on a background image. + * [Read more about Drag & Drop captcha](https://2captcha.com/2captcha-api#drag-and-drop-captcha). + * + * @param {{ body, images, textinstructions, language, lang, pingback }} params Parameters Drag & Drop Captcha as an object. + * @param {string} params.body Background image encoded into Base64 format, without the `data:image/...;base64,` prefix. + * @param {string[]} params.images Array of Base64-encoded images to drag. Order matters — the same order is used in the response. + * @param {string} params.textinstructions Optional. Text with instruction for solving the captcha, up to 140 characters. For example: "Drag the images to proper position". + * @param {number} params.language Optional. `0` - not specified. `1` - Cyrillic captcha. `2` - Latin captcha. + * @param {string} params.lang Optional. Language code. [See the list of supported languages](https://2captcha.com/2captcha-api#language). + * @param {string} params.pingback Optional. URL for pingback (callback) response that will be sent when captcha is solved. [More info here](https://2captcha.com/2captcha-api#pingback). + * + * @returns {Promise} The result from the solve. `data` is a pipe-separated string of coordinates, for example `"120,340|null|210,90"`. `null` means the corresponding image wasn't moved. + * @throws APIError + * + * @example + * const backgroundBase64 = fs.readFileSync("./media/drag_drop_main.jpeg", "base64") + * const imagesBase64 = [ + * fs.readFileSync("./media/drag_drop_image1.jpeg", "base64"), + * fs.readFileSync("./media/drag_drop_image2.jpeg", "base64") + * ] + * + * solver.dragAndDrop({ + * body: backgroundBase64, + * images: imagesBase64, + * textinstructions: "Drag the images to proper position" + * }) + * .then((res) => { + * console.log(res); + * }) + * .catch((err) => { + * console.log(err); + * }) + */ +public async dragAndDrop(params: paramsDragAndDrop): Promise { + checkCaptchaParams(params, "drag_drop") + + const payload = { + ...this.defaultPayload, + ...params, + method: "drag_drop", + }; + + const response = await fetch(this.in, { + body: JSON.stringify(payload), + method: "post", + headers: { "Content-Type": "application/json" } + }) + const result = await response.text() + + let data; + try { + data = JSON.parse(result) + } catch { + throw new APIError(result) + } + + if (data.status == 1) { + return this.pollResponse(data.request) + } else { + throw new APIError(data.request) + } +} + /** * Reports a captcha as correctly solved. * diff --git a/src/utils/checkCaptchaParams.ts b/src/utils/checkCaptchaParams.ts index df5a407..4d8b3f9 100644 --- a/src/utils/checkCaptchaParams.ts +++ b/src/utils/checkCaptchaParams.ts @@ -1,7 +1,7 @@ // Captcha methods for which parameter checking is available const supportedMethods = ["userrecaptcha", "hcaptcha", "geetest", "geetest_v4","yandex","funcaptcha","lemin","amazon_waf", "turnstile", "base64", "capy","datadome", "cybersiara", "mt_captcha", "bounding_box", 'friendly_captcha', 'grid', - 'textcaptcha', 'canvas', 'rotatecaptcha', 'keycaptcha', 'cutcaptcha', 'tencent', 'atb_captcha', 'prosopo', 'captchafox', 'vkimage', 'vkcaptcha', 'temu', 'altcha', 'binance', 'audio', 'yidun', 'alibaba', 'tspd', 'basilisk', 'hunt'] + 'textcaptcha', 'canvas', 'rotatecaptcha', 'keycaptcha', 'cutcaptcha', 'tencent', 'atb_captcha', 'prosopo', 'captchafox', 'vkimage', 'vkcaptcha', 'temu', 'altcha', 'binance', 'audio', 'yidun', 'alibaba', 'tspd', 'basilisk', 'hunt', 'drag_drop'] // Names of required fields that must be contained in the parameters captcha const recaptchaRequiredFields = ['pageurl','googlekey'] @@ -42,6 +42,7 @@ const alibabaRequiredFields = ['pageurl', 'scene_id', 'prefix'] const tspdRequiredFields = ['pageurl', 'tspd_cookie', 'html_page_base64', 'proxy', 'proxytype'] const basiliskRequiredFields = ['pageurl', 'sitekey'] const huntRequiredFields = ['pageurl', 'api_get_lib'] +const dragAndDropRequiredFields = ['body', 'images'] /** * Getting required arguments for a captcha. @@ -164,6 +165,9 @@ const getRequiredFildsArr = (method: string):Array => { case "hunt": requiredFieldsArr = huntRequiredFields break; + case "drag_drop": + requiredFieldsArr = dragAndDropRequiredFields + break; } return requiredFieldsArr }