rucaptcha-2captcha
Advanced tools
Comparing version 1.0.5 to 2.0.0
{ | ||
"name": "rucaptcha-2captcha", | ||
"version": "1.0.5", | ||
"version": "2.0.0", | ||
"description": "Operates with RuCaptcha.com and 2Captcha.com services conveniently.", | ||
@@ -26,2 +26,3 @@ "main": "ruCaptcha2Captcha.js", | ||
"hcaptcha", | ||
"clickcaptcha", | ||
"capy-puzzle", | ||
@@ -32,3 +33,6 @@ "rotatecaptcha", | ||
], | ||
"author": "ArthurKa", | ||
"author": { | ||
"name": "ArthurKa", | ||
"email": "arthur.katruk@gmail.com" | ||
}, | ||
"license": "ISC", | ||
@@ -40,4 +44,5 @@ "bugs": { | ||
"dependencies": { | ||
"axios": "^0.19.2" | ||
"axios": "^0.19.2", | ||
"cheerio": "^1.0.0-rc.3" | ||
} | ||
} |
169
README.md
@@ -1,9 +0,15 @@ | ||
[![All dependencies](https://img.shields.io/librariesio/release/npm/rucaptcha-2captcha/1.0.5?style=flat-square "All dependencies of rucaptcha-2captcha@1.0.5")](https://libraries.io/npm/rucaptcha-2captcha/1.0.5) | ||
[![Reported vulnerabilities](https://img.shields.io/snyk/vulnerabilities/npm/rucaptcha-2captcha@1.0.5?style=flat-square "Reported vulnerabilities of rucaptcha-2captcha@1.0.5")](https://snyk.io/test/npm/rucaptcha-2captcha/1.0.5) | ||
[![NPM-version](https://img.shields.io/badge/npm-v1.0.5-blue.svg?style=flat-square&&logo=npm "Current NPM-version")](https://www.npmjs.com/package/rucaptcha-2captcha/v/1.0.5) | ||
[![Install size](https://flat.badgen.net/packagephobia/install/rucaptcha-2captcha@1.0.5?label=size 'Install size of rucaptcha-2captcha@1.0.5')](https://packagephobia.now.sh/result?p=rucaptcha-2captcha@1.0.5) | ||
[![All dependencies](https://img.shields.io/librariesio/release/npm/rucaptcha-2captcha/2.0.0?style=flat-square "All dependencies of rucaptcha-2captcha@2.0.0")](https://libraries.io/npm/rucaptcha-2captcha/2.0.0) | ||
[![Reported vulnerabilities](https://img.shields.io/snyk/vulnerabilities/npm/rucaptcha-2captcha@2.0.0?style=flat-square "Reported vulnerabilities of rucaptcha-2captcha@2.0.0")](https://snyk.io/test/npm/rucaptcha-2captcha/2.0.0) | ||
[![Commits](https://flat.badgen.net/github/commits/ArthurKa/rucaptcha-2captcha)](https://github.com/ArthurKa/rucaptcha-2captcha/commits/master) | ||
[![NPM-version](https://img.shields.io/badge/npm-v2.0.0-blue.svg?style=flat-square&&logo=npm "Current NPM-version")](https://www.npmjs.com/package/rucaptcha-2captcha/v/2.0.0) | ||
[![Total downloads](https://img.shields.io/npm/dt/rucaptcha-2captcha?style=flat-square "Total downloads for all the time")](https://npm-stat.com/charts.html?package=rucaptcha-2captcha) | ||
[![Developed by](https://img.shields.io/badge/developed_by-ArthurKa-blueviolet.svg?style=flat-square "Have any questions? You are always welcome.")](https://github.com/ArthurKa/rucaptcha-2captcha/issues) | ||
# rucaptcha-2captcha@1.0.5 | ||
[![Publish size](https://flat.badgen.net/packagephobia/publish/rucaptcha-2captcha@2.0.0?label=publish 'Publish size of rucaptcha-2captcha@2.0.0')](https://packagephobia.now.sh/result?p=rucaptcha-2captcha@2.0.0) | ||
[![Install size](https://flat.badgen.net/packagephobia/install/rucaptcha-2captcha@2.0.0?label=install 'Install size of rucaptcha-2captcha@2.0.0')](https://packagephobia.now.sh/result?p=rucaptcha-2captcha@2.0.0) | ||
[![Minified size](https://img.shields.io/bundlephobia/min/rucaptcha-2captcha@2.0.0?style=flat-square&label=minified "Minified size of rucaptcha-2captcha@2.0.0")](https://bundlephobia.com/result?p=rucaptcha-2captcha@2.0.0) | ||
[![Minified + gzipped size](https://img.shields.io/bundlephobia/minzip/rucaptcha-2captcha@2.0.0?style=flat-square&label=minzipped "Minified + gzipped size of rucaptcha-2captcha@2.0.0")](https://bundlephobia.com/result?p=rucaptcha-2captcha@2.0.0) | ||
# rucaptcha-2captcha@2.0.0 | ||
Helps you to operate with [RuCaptcha] or [2Captcha] services conveniently. | ||
@@ -16,3 +22,3 @@ | ||
``` bash | ||
$ npm i rucaptcha-2captcha@1.0.5 | ||
$ npm i rucaptcha-2captcha@2.0.0 | ||
``` | ||
@@ -29,3 +35,3 @@ | ||
| apiKey | string | yes | Your account API key from settings ([RuCaptcha][RuCaptchaSettings] \| [2Captcha][2CaptchaSettings]). | ||
| type | string | no | Case insensitive **'2captcha'** for [2Captcha].<br>Any other for [RuCaptcha]. | ||
| type | string | no | Provide string or number **2** for [2Captcha].<br>Any other for [RuCaptcha]. | ||
@@ -39,3 +45,3 @@ #### Example | ||
// or for operating with 2Captcha.com | ||
const captchaSolver = new RuCaptcha2Captcha(<YOUR_API_KEY>, '2captcha'); | ||
const captchaSolver = new RuCaptcha2Captcha(<YOUR_API_KEY>, 2); | ||
@@ -47,7 +53,7 @@ ``` | ||
captchaSolver.send(params) → `Promise<Object { request: String<captcha_id> }>` | ||
captchaSolver.send(params) → `Promise<captcha_id>` | ||
| Name | Type | Required | Description | ||
|--------|--------|----------|- | ||
| params | object | yes | Object with properties from documentation ([RuCaptcha][RuCaptchaParams] \| [2Captcha][2CaptchaParams]).<br>Except: `key`, `json` and `soft_id`. | ||
| params | object | yes | Object with properties from documentation ([RuCaptcha][RuCaptchaParams] \| [2Captcha][2CaptchaParams]),<br>except: `key`, `json` and `soft_id`.<br>Of properties `url`, `method`, `file` and `body`<br>use only one of the next combinations:<br> • `url`<br> • `method` + `file`<br> • `method` + `body` | ||
@@ -61,4 +67,4 @@ Use this method to send captcha for solving. | ||
body: <base64_image_body>, | ||
// any other parameter from documentation | ||
// except: key, json and soft_id | ||
// any other parameter from documentation, | ||
// except: file, key, json and soft_id | ||
}); | ||
@@ -68,27 +74,18 @@ | ||
``` | ||
### captchaSolver.sendFile custom method over captchaSolver.send | ||
#### Synopsis | ||
captchaSolver.sendFile(filePath[, params]) → `Promise<Object { request: String<captcha_id> }>` | ||
| Name | Type | Required | Description | ||
|----------|--------|----------|- | ||
| filePath | string | yes | Path to captcha image on your file system. | ||
| params | object | no | Object with properties from documentation ([RuCaptcha][RuCaptchaParams] \| [2Captcha][2CaptchaParams]).<br>Except: `method`, `file`, `body`, `key`, `json` and `soft_id`. | ||
Use this method to send captcha as image from your local file system. | ||
#### Example | ||
#### Sending image from your local file system or the Internet | ||
```js | ||
const id = await captchaSolver.sendFile('./captcha.jpg', { | ||
min_len: 6, | ||
max_len: 6, | ||
regsense: 1, | ||
numeric: 4, | ||
// any other parameter from documentation | ||
const id = await captchaSolver.send({ | ||
// url: './captchas/W68HP.gif', | ||
url: 'https://user-images.githubusercontent.com/16370704/87232185-aad0b680-c3c5-11ea-8cfc-b769bba631d4.gif', | ||
// any other parameter from documentation, | ||
// except: method, file, body, key, json and soft_id | ||
// for example | ||
regsense: 1, // for case-sensitive | ||
numeric: 4, // for both numbers and letters | ||
min_len: 5, | ||
max_len: 5, // for exact 5 symbols | ||
language: 2, // for Roman alphabet | ||
}); | ||
// id: '4503599627' | ||
// id: '4503599672' | ||
``` | ||
@@ -144,10 +141,56 @@ | ||
const result = await captchaSolver.reportBad(id); | ||
// result: { status: 1, request: 'OK_REPORT_RECORDED' } | ||
``` | ||
### captchaSolver.get2 method | ||
### captchaSolver.solve method | ||
#### Synopsis | ||
captchaSolver.get2(id) → `Promise<Object>` | ||
captchaSolver.solve(params) → `Promise<Object { token, tokenIsGood, tokenIsBad }>` | ||
##### Request | ||
| Name | Type | Required | Description | ||
|--------|--------|----------|- | ||
| params | object | yes | The same properties as for [captchaSolver.send](#captchasolversend-method) method. | ||
##### Response | ||
| Name | Type | Description | ||
|-------------|----------|- | ||
| token | string | Solved captcha token. | ||
| tokenIsGood | function | Callback function for reporting received token is correct. | ||
| tokenIsBad | function | Callback function for reporting received token is wrong. | ||
captchaSolver.solve method is nothing more but convenient bundle of next methods: | ||
- captchaSolver.send | ||
- captchaSolver.get | ||
- captchaSolver.reportGood | ||
- captchaSolver.reportBad | ||
You still can use them on your own. | ||
#### Example | ||
```js | ||
const { token, tokenIsGood, tokenIsBad } = await captchaSolver.solve({ | ||
url: 'https://user-images.githubusercontent.com/16370704/87232185-aad0b680-c3c5-11ea-8cfc-b769bba631d4.gif', | ||
regsense: 1, // for case-sensitive | ||
numeric: 4, // for both numbers and letters | ||
min_len: 5, | ||
max_len: 5, // for exact 5 symbols | ||
language: 2, // for Roman alphabet | ||
}); | ||
if(token === 'W68HP') { | ||
console.log('Everything is just fine.'); | ||
await tokenIsGood(); | ||
} else { | ||
console.log('Captcha was solved incorrect:', token); | ||
await tokenIsBad(); | ||
} | ||
``` | ||
### captchaSolver.getWithPrice method | ||
#### Synopsis | ||
captchaSolver.getWithPrice(id) → `Promise<Object>` | ||
| Name | Type | Required | Description | ||
@@ -157,8 +200,8 @@ |------|--------|----------|- | ||
Use captchaSolver.get2 method for getting captcha answer with its cost price. | ||
Use captchaSolver.getWithPrice method for getting captcha answer with its cost price. | ||
#### Example | ||
```js | ||
const info = await captchaSolver.get2(id); | ||
// info: { request: '6p6pck', price: '0.034' } | ||
const info = await captchaSolver.getWithPrice(id); | ||
// info: { token: '6p6pck', price: '0.034' } | ||
``` | ||
@@ -169,3 +212,3 @@ | ||
captchaSolver.captchaSolver.getBalance() → `Promise<number>` | ||
captchaSolver.getBalance() → `Promise<number>` | ||
@@ -181,2 +224,48 @@ Use for getting your account balance.\ | ||
### captchaSolver.getPrices method | ||
#### Synopsis | ||
captchaSolver.getPrices() → `Promise<Object>` | ||
Use for getting actual service prices.\ | ||
Note: this method does not decrease your API query limit. | ||
#### Example | ||
```js | ||
const prices = await captchaSolver.getPrices(); | ||
// Warning! That is current actual prices. Prices and categories can change! | ||
/* | ||
prices in RUR for RuCaptcha service: { | ||
'Обычная капча': 0.023, | ||
'Текстовая капча': 0.023, | ||
'ReCaptcha V2': 0.16, | ||
'ReCaptcha V3': 0.16, | ||
GeeTest: 0.16, | ||
hCaptcha: 0.16, | ||
'Capy Puzzle': 0.16, | ||
'ReCaptcha V2 (старый метод)': 0.07, | ||
ClickCaptcha: 0.07, | ||
RotateCaptcha: 0.035, | ||
'FunCaptcha с токеном': 0.16, | ||
KeyCaptcha: 0.16 | ||
} | ||
prices in USD for 2Captcha service: { | ||
'Normal Captcha': 0.00079, | ||
'Text Captcha': 0.00079, | ||
'ReCaptcha V2': 0.00299, | ||
'ReCaptcha V3': 0.00299, | ||
GeeTest: 0.00299, | ||
'ReCaptcha V2 (old method)': 0.0012, | ||
'Solving ClickCaptcha': 0.0012, | ||
RotateCaptcha: 0.0005, | ||
FunCaptcha: 0.0005, | ||
'FunCaptcha Token Method': 0.00299, | ||
KeyCaptcha: 0.00299, | ||
hCaptcha: 0.00299, | ||
Capy: 0.00299 | ||
} | ||
*/ | ||
``` | ||
--- | ||
@@ -191,3 +280,3 @@ | ||
Your improve suggestions and bug reports are welcome any time. | ||
Your improve suggestions and bug reports [are welcome](https://github.com/ArthurKa/rucaptcha-2captcha/issues) any time. | ||
@@ -194,0 +283,0 @@ [RuCaptcha]: https://rucaptcha.com |
@@ -5,2 +5,3 @@ 'use strict'; | ||
const axios = require('axios'); | ||
const cheerio = require('cheerio'); | ||
@@ -17,3 +18,3 @@ const wait = s => new Promise(res => setTimeout(res, s * 1000)); | ||
function RuCaptcha2Captcha(key, twoCaptcha = '') { | ||
function RuCaptcha2Captcha(key, twoCaptcha = null) { | ||
if(!new.target) { | ||
@@ -23,11 +24,38 @@ return new RuCaptcha2Captcha(key, twoCaptcha); | ||
const ruOr2 = String(twoCaptcha).toLowerCase().trim() === '2captcha' ? 2 : 'ru'; | ||
const sendUrl = `https://${ruOr2}captcha.com/in.php`; | ||
const getUrl = `https://${ruOr2}captcha.com/res.php`; | ||
const isRuCaptcha = ![2, '2'].includes(twoCaptcha); | ||
const domain = `https://${isRuCaptcha ? 'ru' : 2}captcha.com`; | ||
const sendUrl = `${domain}/in.php`; | ||
const getUrl = `${domain}/res.php`; | ||
const priceUrls = { | ||
all: isRuCaptcha ? 'https://rucaptcha.com/api-rucaptcha#rates' : 'https://2captcha.com/2captcha-api#rates', | ||
normal: `${domain}/public_statistics`, | ||
}; | ||
const waits = {}; | ||
this.send = async parameters => { | ||
this.send = async ({ url, method, file, body, ...restParams }) => { | ||
let p = { | ||
method, | ||
file, | ||
body, | ||
}; | ||
if(url) { | ||
let buffer; | ||
try { | ||
buffer = fs.readFileSync(url); | ||
} catch(e) { | ||
const { data } = await axios.get(url, { responseType: 'arraybuffer' }); | ||
buffer = Buffer.from(data, 'binary'); | ||
} | ||
p = { | ||
method: 'base64', | ||
body: buffer.toString('base64'), | ||
}; | ||
} | ||
const params = { | ||
...parameters, | ||
...Object.fromEntries(Object.entries(p).filter(e => e[1] != null)), | ||
...restParams, | ||
key, | ||
@@ -42,4 +70,4 @@ json: 1, | ||
const method = (params.method || '').toLowerCase(); | ||
const timeToWaitInSeconds = ['post', 'base64', ''].includes(method) && params.recaptcha == null && params.coordinatescaptcha == null | ||
const m = (params.method || '').toLowerCase(); | ||
const timeToWaitInSeconds = ['post', 'base64', ''].includes(m) && params.recaptcha == null && params.coordinatescaptcha == null | ||
? 5 | ||
@@ -49,15 +77,5 @@ : 20; | ||
return data; | ||
return id; | ||
}; | ||
this.sendFile = (filePath, { file, ...params } = {}) => { | ||
const body = fs.readFileSync(filePath).toString('base64'); | ||
return this.send({ | ||
...params, | ||
method: 'base64', | ||
body, | ||
}); | ||
}; | ||
this.get = async id => { | ||
@@ -101,3 +119,3 @@ const ids = String(id).split(/\s*,\s*/); | ||
this.get2 = async id => { | ||
this.getWithPrice = async id => { | ||
id = String(id); | ||
@@ -119,3 +137,4 @@ while(1) { | ||
if(data.request !== 'CAPCHA_NOT_READY') { | ||
return data; | ||
const { request: token, ...rest } = data; | ||
return { token, ...rest }; | ||
} | ||
@@ -127,20 +146,18 @@ | ||
const makeReport = type => { | ||
return id => axios | ||
.get(getUrl, { | ||
params: { | ||
key, | ||
action: `report${type}`, | ||
id, | ||
json: 1, | ||
}, | ||
}) | ||
.then(e => e.data) | ||
.catch(e => { | ||
if(e.message === 'Request failed with status code 500') { | ||
return { status: 1, request: 'OK_REPORT_RECORDED' }; | ||
} | ||
throw e; | ||
}); | ||
}; | ||
const makeReport = type => id => axios | ||
.get(getUrl, { | ||
params: { | ||
key, | ||
action: `report${type}`, | ||
id, | ||
json: 1, | ||
}, | ||
}) | ||
.then(e => e.data) | ||
.catch(e => { | ||
if(e.message === 'Request failed with status code 500') { | ||
return { status: 1, request: 'OK_REPORT_RECORDED' }; | ||
} | ||
throw e; | ||
}); | ||
@@ -160,4 +177,57 @@ this.reportBad = makeReport('bad'); | ||
}; | ||
this.getPrices = async () => { | ||
const nornamNames = []; | ||
const [normalPrice, otherPrices] = await Promise.all([ | ||
axios.get(priceUrls.normal).then(({ data }) => { | ||
const $ = cheerio.load(data, { decodeEntities: false }); | ||
return +($($('#market-price').toArray()[0]).text() / 1000).toFixed(7); | ||
}), | ||
axios.get(priceUrls.all).then(({ data }) => { | ||
const $ = cheerio.load(data, { decodeEntities: false }); | ||
const table = $($('.table').toArray().find(e => $(e).text().match(/Type of captcha|Вид капчи/i))); | ||
return table.find('tr').toArray().slice(1).reduce((obj, e) => { | ||
const [types, price] = $(e).find('td').toArray().map((e, i) => { | ||
if(!i) { | ||
return $(e).find('a').toArray(); | ||
} | ||
return e; | ||
}); | ||
const p = +($(price).text().replace(/\$/g, '') / 1000).toFixed(7); | ||
for(const type of types) { | ||
const t = $(type).text().trim(); | ||
if(isNaN(p)) { | ||
nornamNames.push(t); | ||
} else { | ||
obj[t] = p; | ||
} | ||
} | ||
return obj; | ||
}, {}); | ||
}), | ||
]); | ||
const normalPrices = Object.fromEntries(nornamNames.map(e => [e, normalPrice])); | ||
return { | ||
...normalPrices, | ||
...otherPrices, | ||
}; | ||
}; | ||
this.solve = async (...params) => { | ||
const id = await this.send(...params); | ||
const token = await this.get(id); | ||
return { | ||
token, | ||
tokenIsGood: this.reportGood.bind(null, id), | ||
tokenIsBad: this.reportBad.bind(null, id), | ||
}; | ||
}; | ||
}; | ||
module.exports = RuCaptcha2Captcha; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
16846
186
280
2
+ Addedcheerio@^1.0.0-rc.3
+ Addedboolbase@1.0.0(transitive)
+ Addedcheerio@1.0.0(transitive)
+ Addedcheerio-select@2.1.0(transitive)
+ Addedcss-select@5.1.0(transitive)
+ Addedcss-what@6.1.0(transitive)
+ Addeddom-serializer@2.0.0(transitive)
+ Addeddomelementtype@2.3.0(transitive)
+ Addeddomhandler@5.0.3(transitive)
+ Addeddomutils@3.1.0(transitive)
+ Addedencoding-sniffer@0.2.0(transitive)
+ Addedentities@4.5.0(transitive)
+ Addedhtmlparser2@9.1.0(transitive)
+ Addediconv-lite@0.6.3(transitive)
+ Addednth-check@2.1.1(transitive)
+ Addedparse5@7.2.1(transitive)
+ Addedparse5-htmlparser2-tree-adapter@7.1.0(transitive)
+ Addedparse5-parser-stream@7.1.2(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedundici@6.21.0(transitive)
+ Addedwhatwg-encoding@3.1.1(transitive)
+ Addedwhatwg-mimetype@4.0.0(transitive)