ruby-2captcha 1.0.2 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec_status +7 -5
- data/.ruby-version +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +47 -14
- data/README.ru.md +340 -0
- data/lib/api_2captcha/client.rb +220 -214
- data/lib/api_2captcha/version.rb +1 -1
- data/lib/api_2captcha.rb +3 -3
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cc7d94f83479f1d8c57bb4cf2315a2fcb04475a7c9f2ca170b09648d95d830e
|
4
|
+
data.tar.gz: 759ff2de9c3fed201fcb467e52b4fe2c0d24af9c006596ed58002c3b2f7b42b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c9f92edcd7270fa86a6fcc287734596c8a9de31bb491451ab2569adb3d555c104716436cfb386dab9d95e0a4bb747a85e6a4dfc7ff705c4ae2b31689e8615ad
|
7
|
+
data.tar.gz: 71bd866a8dfe6e82b49abe66537ec7d2b0bcdef58e6e2bace9f9fc024a0e21e071aaa021cca517a31bf2f1d2b3296c94ece3485a76dab9d2d92190aab86c84aa
|
data/.rspec_status
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
example_id | status | run_time
|
2
|
-
---------------------------------- | ------ |
|
3
|
-
./spec/api_2captcha_spec.rb[1:1] | passed | 0.
|
4
|
-
./spec/api_2captcha_spec.rb[1:2:1] | passed | 0.
|
5
|
-
./spec/api_2captcha_spec.rb[1:3:1] | passed |
|
1
|
+
example_id | status | run_time |
|
2
|
+
---------------------------------- | ------ | --------------------- |
|
3
|
+
./spec/api_2captcha_spec.rb[1:1] | passed | 0.04326 seconds |
|
4
|
+
./spec/api_2captcha_spec.rb[1:2:1] | passed | 0.00121 seconds |
|
5
|
+
./spec/api_2captcha_spec.rb[1:3:1] | passed | 3.15 seconds |
|
6
|
+
./spec/api_2captcha_spec.rb[1:4:1] | passed | 2 minutes 0.2 seconds |
|
7
|
+
./spec/api_2captcha_spec.rb[1:5:1] | passed | 0.26142 seconds |
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.6.0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -10,8 +10,9 @@ A Ruby client for the 2Captcha API.
|
|
10
10
|
- [Solve captcha](#solve-captcha)
|
11
11
|
- [Normal Captcha](#normal-captcha)
|
12
12
|
- [Text](#text-captcha)
|
13
|
-
- [
|
14
|
-
- [
|
13
|
+
- [reCAPTCHA v2](#recaptcha-v2)
|
14
|
+
- [reCAPTCHA v3](#recaptcha-v3)
|
15
|
+
- [reCAPTCHA Enterprise](#recaptcha-enterprise)
|
15
16
|
- [GeeTest](#geetest)
|
16
17
|
- [hCaptcha](#hcaptcha)
|
17
18
|
- [KeyCaptcha](#keycaptcha)
|
@@ -25,14 +26,14 @@ A Ruby client for the 2Captcha API.
|
|
25
26
|
- [Lemin Cropped Captcha](#lemin-cropped-captcha)
|
26
27
|
- [GeeTest V4](#geetest-v4)
|
27
28
|
- [Audio](#audio)
|
29
|
+
- [Yandex](#yandex)
|
28
30
|
- [Other methods](#other-methods)
|
29
|
-
- [send /
|
31
|
+
- [send / get_result](#send--getresult)
|
30
32
|
- [balance](#balance)
|
31
33
|
- [report](#report)
|
32
34
|
- [Error handling](#error-handling)
|
33
35
|
|
34
36
|
## Installation
|
35
|
-
|
36
37
|
Add this line to your application's Gemfile:
|
37
38
|
|
38
39
|
```bash
|
@@ -54,7 +55,7 @@ $ gem install ruby-2captcha
|
|
54
55
|
To use the api2captcha gem, you'll need to import the module and create a Client instance. Here's an example:
|
55
56
|
|
56
57
|
```ruby
|
57
|
-
require '
|
58
|
+
require 'api_2captcha'
|
58
59
|
|
59
60
|
client = Api2Captcha.new("YOUR_API_KEY")
|
60
61
|
```
|
@@ -71,11 +72,11 @@ client.api_key = "YOUR_API_KEY"
|
|
71
72
|
|---|---|---|
|
72
73
|
|soft_id|-|your software ID obtained after publishing in [2captcha sofware catalog]|
|
73
74
|
|callback|-|URL of your web-sever that receives the captcha recognition result. The URl should be first registered in [pingback settings] of your account|
|
74
|
-
|default_timeout|120|Timeout in seconds for all captcha types except
|
75
|
+
|default_timeout|120|Timeout in seconds for all captcha types except reCAPTCHA. Defines how long the module tries to get the answer from `res.php` API endpoint|
|
75
76
|
|polling_interval|10|Interval in seconds between requests to `res.php` API endpoint, setting values less than 5 seconds is not recommended|
|
76
77
|
|
77
78
|
> **IMPORTANT:** once `callback` is defined for `Client` instance, all methods return only the captcha ID and DO NOT poll the API to get the result. The result will be sent to the callback URL.
|
78
|
-
To get the answer manually use [
|
79
|
+
To get the answer manually use [get_result method](#send--getresult)
|
79
80
|
|
80
81
|
## Solve captcha
|
81
82
|
When you submit any image-based captcha use can provide additional options to help 2captcha workers to solve it properly.
|
@@ -93,7 +94,8 @@ When you submit any image-based captcha use can provide additional options to he
|
|
93
94
|
| hint_image | - | an image with hint shown to workers with the captcha, translated into instructionsimg API parameter |
|
94
95
|
| hint_text | - | hint or task text shown to workers with the captcha |
|
95
96
|
|
96
|
-
Below you can find basic examples for every captcha type
|
97
|
+
Below you can find basic examples for every captcha type, check out the code below.
|
98
|
+
|
97
99
|
|
98
100
|
### Normal Captcha
|
99
101
|
To bypass a normal captcha (distorted text on image) use the following method. This method also can be used to recognize any text on the image.
|
@@ -114,8 +116,8 @@ result = client.text({
|
|
114
116
|
})
|
115
117
|
```
|
116
118
|
|
117
|
-
###
|
118
|
-
Use this method to solve
|
119
|
+
### reCAPTCHA v2
|
120
|
+
Use this method to solve reCAPTCHA V2 and obtain a token to bypass the protection.
|
119
121
|
```ruby
|
120
122
|
result = client.recaptcha_v2({
|
121
123
|
googlekey: '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
@@ -124,8 +126,8 @@ result = client.recaptcha_v2({
|
|
124
126
|
})
|
125
127
|
```
|
126
128
|
|
127
|
-
###
|
128
|
-
This method provides
|
129
|
+
### reCAPTCHA v3
|
130
|
+
This method provides reCAPTCHA V3 solver and returns a token.
|
129
131
|
```ruby
|
130
132
|
result = client.recaptcha_v3({
|
131
133
|
googlekey: '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
@@ -136,6 +138,28 @@ result = client.recaptcha_v3({
|
|
136
138
|
})
|
137
139
|
```
|
138
140
|
|
141
|
+
### reCAPTCHA Enterprise
|
142
|
+
reCAPTCHA Enterprise can be used as reCAPTCHA V2 and reCAPTCHA V3. Below is a usage example for both versions.
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
# reCAPTCHA V2
|
146
|
+
result = client.recaptcha_v2({
|
147
|
+
googlekey: '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
148
|
+
pageurl: 'https://mysite.com/page/with/recaptcha_v2_enterprise',
|
149
|
+
enterprise: 1
|
150
|
+
})
|
151
|
+
|
152
|
+
# reCAPTCHA V3
|
153
|
+
result = client.recaptcha_v3({
|
154
|
+
googlekey: '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
155
|
+
pageurl: 'https://mysite.com/page/with/recaptcha_v3_enterprise',
|
156
|
+
version: 'v3',
|
157
|
+
score: 0.3,
|
158
|
+
action: 'verify',
|
159
|
+
enterprise: 1,
|
160
|
+
})
|
161
|
+
```
|
162
|
+
|
139
163
|
### FunCaptcha
|
140
164
|
FunCaptcha (Arkoselabs) solving method. Returns a token.
|
141
165
|
|
@@ -189,7 +213,7 @@ result = client.capy({
|
|
189
213
|
```
|
190
214
|
|
191
215
|
### Grid
|
192
|
-
Grid method is originally called Old
|
216
|
+
Grid method is originally called Old reCAPTCHA V2 method. The method can be used to bypass any type of captcha where you can apply a grid on image and need to click specific grid boxes. Returns numbers of boxes.
|
193
217
|
```ruby
|
194
218
|
result = client.grid({
|
195
219
|
image: 'path/to/captcha.jpg',
|
@@ -288,9 +312,18 @@ result = client.audio({
|
|
288
312
|
})
|
289
313
|
```
|
290
314
|
|
315
|
+
### Yandex
|
316
|
+
Use this method to solve Yandex and obtain a token to bypass the protection.
|
317
|
+
```ruby
|
318
|
+
result = client.yandex({
|
319
|
+
sitekey: 'Y5Lh0tiycconMJGsFd3EbbuNKSp1yaZESUOIHfeV',
|
320
|
+
url: "https://rutube.ru"
|
321
|
+
})
|
322
|
+
```
|
323
|
+
|
291
324
|
## Other methods
|
292
325
|
|
293
|
-
### send /
|
326
|
+
### send / get_result
|
294
327
|
These methods can be used for manual captcha submission and answer polling.
|
295
328
|
```ruby
|
296
329
|
|
data/README.ru.md
ADDED
@@ -0,0 +1,340 @@
|
|
1
|
+
# Ruby 2Captcha API Client
|
2
|
+
|
3
|
+
Это самый простой способ быстро интегрировать 2Captcha в ваш код и автоматизировать решение любого типа капчи.
|
4
|
+
|
5
|
+
Ruby-клиент для API 2Captcha.
|
6
|
+
|
7
|
+
- [Установка](#installation)
|
8
|
+
- [Настройка](#configuration)
|
9
|
+
- [Опции экземпляра клиента](#client-instance-options)
|
10
|
+
- [Решение капчи](#solve-captcha)
|
11
|
+
- [Обычная капча](#normal-captcha)
|
12
|
+
- [Текстовая капча](#text-captcha)
|
13
|
+
- [ReCaptcha v2](#recaptcha-v2)
|
14
|
+
- [ReCaptcha v3](#recaptcha-v3)
|
15
|
+
- [GeeTest](#geetest)
|
16
|
+
- [hCaptcha](#hcaptcha)
|
17
|
+
- [KeyCaptcha](#keycaptcha)
|
18
|
+
- [Capy](#capy)
|
19
|
+
- [Grid](#grid)
|
20
|
+
- [Canvas](#canvas)
|
21
|
+
- [ClickCaptcha](#clickcaptcha)
|
22
|
+
- [Rotate](#rotate)
|
23
|
+
- [AmazonWAF](#amazon-waf)
|
24
|
+
- [CloudflareTurnstile](#cloudflare-turnstile)
|
25
|
+
- [Lemin Cropped Captcha](#lemin-cropped-captcha)
|
26
|
+
- [GeeTest V4](#geetest-v4)
|
27
|
+
- [Аудио](#audio)
|
28
|
+
- [Другие методы](#other-methods)
|
29
|
+
- [send / get_result](#send--getresult)
|
30
|
+
- [balance](#balance)
|
31
|
+
- [report](#report)
|
32
|
+
- [Обработка ошибок](#error-handling)
|
33
|
+
|
34
|
+
## Установка
|
35
|
+
Автоматическая установка гема с помощью Bundler. Добавьте следующую строку в ваш Gemfile:
|
36
|
+
```ruby
|
37
|
+
gem 'ruby-2captcha'
|
38
|
+
```
|
39
|
+
Затем выполните следующую команду в терминале:
|
40
|
+
```ruby
|
41
|
+
bundle install
|
42
|
+
```
|
43
|
+
|
44
|
+
Или установите его самостоятельно, выполнив следующую команду в терминале:
|
45
|
+
```ruby
|
46
|
+
gem install ruby-2captcha
|
47
|
+
```
|
48
|
+
|
49
|
+
Мы также приглашаем вас ознакомиться с нашим репозиторием на [GitHub](https://github.com/2captcha/), где вы можете найти библиотеки и модули для простой интеграции с нашим API.
|
50
|
+
|
51
|
+
## Настройка
|
52
|
+
|
53
|
+
Описание всех необходимых параметров для настройки установленного гема.
|
54
|
+
|
55
|
+
Экземпляр класса Api2Captcha можно создать следующим образом:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
require 'api_2captcha'
|
59
|
+
|
60
|
+
client = Api2Captcha.new("YOUR_API_KEY")
|
61
|
+
```
|
62
|
+
|
63
|
+
У вас также есть возможность настроить некоторые параметры экземпляра Api2Captcha:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
client.soft_id(123)
|
67
|
+
client.domain("https://rucaptcha.com/")
|
68
|
+
client.callback("https://your.site/result-receiver")
|
69
|
+
client.default_timeout(120)
|
70
|
+
client.polling_interval(10)
|
71
|
+
```
|
72
|
+
|
73
|
+
**ВАЖНО**: после определения обратного вызова для экземпляра , все методы возвращают только идентификатор капчи и НЕ запрашивают результат у API. Результат будет отправлен на URL обратного вызова. Чтобы получить ответ вручную, используйте метод get_result.
|
74
|
+
|
75
|
+
## Решение капчи
|
76
|
+
При отправке любой капчи, основанной на изображении, вы можете предоставить дополнительные параметры, чтобы помочь работникам 2Captcha правильно ее решить.
|
77
|
+
|
78
|
+
### Параметры капчи
|
79
|
+
|
80
|
+
| Параметр | Значение по умолчанию | Описание |
|
81
|
+
|-------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------|
|
82
|
+
| numeric | 0 | Определяет, содержит ли капча числа или другие символы [подробнее см. в документации по API](https://2captcha.com/2captcha-api#normal_post) |
|
83
|
+
| min_len | 0 | Минимальная длина ответа length |
|
84
|
+
| max_len | 0 | Максимальная длина ответа length |
|
85
|
+
| phrase | 0 | Определяет, содержит ли ответ несколько слов или нет |
|
86
|
+
| case_sensitive | 0 | Определяет, учитывается ли регистр в ответе |
|
87
|
+
| calc | 0 | Определяет, требуется ли вычисление в решении капчи |
|
88
|
+
| lang | - | Определяет язык капчи, см. [список поддерживаемых языков](https://2captcha.com/2captcha-api#language) |
|
89
|
+
| hint_image | - | Изображение с подсказкой, показываемое работникам с капчей, переведенное из параметра API instructionsimg |
|
90
|
+
| hint_text | - | Подсказка или текст задания, показываемые работникам с капчей |
|
91
|
+
|
92
|
+
Ниже вы найдете основные примеры для каждого типа капчи. Ознакомьтесь с кодом ниже.
|
93
|
+
|
94
|
+
### Обычная капча
|
95
|
+
Для обхода обычной капчи (искаженный текст на картинке) используйте следующий метод. Этот метод также может использоваться для распознавания любого текста на картинке.
|
96
|
+
```ruby
|
97
|
+
result = client.normal({ image: 'path/to/captcha.jpg'})
|
98
|
+
# OR
|
99
|
+
result = client.normal({
|
100
|
+
image: 'https://site-with-captcha.com/path/to/captcha.jpg'
|
101
|
+
})
|
102
|
+
```
|
103
|
+
|
104
|
+
### Текстовая капча
|
105
|
+
Этот метод может использоваться для обхода капчи, которая требует ответить на вопрос, представленный в явном виде.
|
106
|
+
```ruby
|
107
|
+
result = client.text({
|
108
|
+
textcaptcha:'Если завтра суббота, то какой сегодня день?',
|
109
|
+
lang: "ru"
|
110
|
+
})
|
111
|
+
```
|
112
|
+
|
113
|
+
### ReCaptcha v2
|
114
|
+
Используйте этот метод для решения ReCaptcha V2 и получения токена для обхода защиты.
|
115
|
+
```ruby
|
116
|
+
result = client.recaptcha_v2({
|
117
|
+
googlekey: '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
118
|
+
pageurl: 'https://mysite.com/page/with/recaptcha_v2',
|
119
|
+
invisible: 1
|
120
|
+
})
|
121
|
+
```
|
122
|
+
|
123
|
+
### ReCaptcha v3
|
124
|
+
Этот метод предоставляет решение для ReCaptcha V3 и возвращает токен.
|
125
|
+
```ruby
|
126
|
+
result = client.recaptcha_v3({
|
127
|
+
googlekey: '6Le-wvkSVVABCPBMRTvw0Q4Muexq1bi0DJwx_mJ-',
|
128
|
+
pageurl: 'https://mysite.com/page/with/recaptcha_v3',
|
129
|
+
version: 'v3',
|
130
|
+
score: 0.3,
|
131
|
+
action: 'verify'
|
132
|
+
})
|
133
|
+
```
|
134
|
+
|
135
|
+
### FunCaptcha
|
136
|
+
Метод решения FunCaptcha (Arkoselabs). Он возвращает токен.
|
137
|
+
```ruby
|
138
|
+
result = client.funcaptcha({
|
139
|
+
publickey: "69A21A01-CC7B-B9C6-0F9A-E7FA06677FFC",
|
140
|
+
pageurl: "https://mysite.com/page/with/funcaptcha",
|
141
|
+
surl: "https://client-api.arkoselabs.com"})
|
142
|
+
```
|
143
|
+
|
144
|
+
### GeeTest
|
145
|
+
Метод для решения головоломки GeeTest captcha. Он возвращает набор токенов в формате JSON.
|
146
|
+
```ruby
|
147
|
+
result = client.geetest({
|
148
|
+
gt: 'f1ab2cdefa3456789012345b6c78d90e',
|
149
|
+
api_server: 'api-na.geetest.com',
|
150
|
+
challenge: '12345678abc90123d45678ef90123a456b',
|
151
|
+
pageurl: 'https://www.site.com/page/'
|
152
|
+
})
|
153
|
+
```
|
154
|
+
|
155
|
+
### hCaptcha
|
156
|
+
Метод решения hCaptcha. Он возвращает токен для обхода капчи.
|
157
|
+
```ruby
|
158
|
+
result = client.hcaptcha({
|
159
|
+
sitekey: '10000000-ffff-ffff-ffff-000000000001',
|
160
|
+
pageurl: 'https://www.site.com/page/'
|
161
|
+
})
|
162
|
+
```
|
163
|
+
|
164
|
+
### KeyCaptcha
|
165
|
+
Метод на основе токенов для решения KeyCaptcha.
|
166
|
+
```ruby
|
167
|
+
result = client.keycaptcha({
|
168
|
+
s_s_c_user_id: 10,
|
169
|
+
s_s_c_session_id: '493e52c37c10c2bcdf4a00cbc9ccd1e8',
|
170
|
+
s_s_c_web_server_sign: '9006dc725760858e4c0715b835472f22-pz-',
|
171
|
+
s_s_c_web_server_sign2: '2ca3abe86d90c6142d5571db98af6714',
|
172
|
+
pageurl: 'https://www.keycaptcha.ru/demo-magnetic/'
|
173
|
+
})
|
174
|
+
```
|
175
|
+
|
176
|
+
### Capy
|
177
|
+
Метод основан на использовании токенов для обхода паззла Capy.
|
178
|
+
```ruby
|
179
|
+
result = client.capy({
|
180
|
+
sitekey: 'PUZZLE_Abc1dEFghIJKLM2no34P56q7rStu8v',
|
181
|
+
pageurl: 'http://mysite.com/',
|
182
|
+
api_server: 'https://jp.api.capy.me/'
|
183
|
+
})
|
184
|
+
```
|
185
|
+
|
186
|
+
### Grid
|
187
|
+
Метод сетки изначально называется методом Old ReCaptcha V2. Этот метод может быть использован для обхода любого типа капчи, где вы можете применить сетку к изображению и необходимо кликнуть по определенным ячейкам сетки. Он возвращает количество выбранных ячеек.
|
188
|
+
```ruby
|
189
|
+
result = client.grid({
|
190
|
+
image: 'path/to/captcha.jpg',
|
191
|
+
rows: 3,
|
192
|
+
cols: 3,
|
193
|
+
previous_id: 0,
|
194
|
+
lang: 'en',
|
195
|
+
hint_image: 'path/to/hint.jpg',
|
196
|
+
hint_text: 'Select all images with an Orange'
|
197
|
+
})
|
198
|
+
```
|
199
|
+
|
200
|
+
### Canvas
|
201
|
+
Метод Canvas может быть использован, когда вам необходимо нарисовать линию вокруг объекта на изображении. Он возвращает набор координат точек для рисования многоугольника.
|
202
|
+
```ruby
|
203
|
+
result = client.canvas({
|
204
|
+
image: 'path/to/captcha.jpg',
|
205
|
+
previous_id: 0,
|
206
|
+
lang: 'en',
|
207
|
+
hint_image: 'path/to/hint.jpg',
|
208
|
+
hint_text: 'Draw around apple'
|
209
|
+
})
|
210
|
+
```
|
211
|
+
|
212
|
+
### ClickCaptcha
|
213
|
+
Метод ClickCaptcha возвращает координаты точек на изображении капчи. Может быть использован, если вам необходимо кликнуть по определенным точкам на изображении.
|
214
|
+
```ruby
|
215
|
+
result = client.coordinates({
|
216
|
+
image: 'path/to/captcha.jpg',
|
217
|
+
lang: 'en',
|
218
|
+
hint_image: 'path/to/hint.jpg',
|
219
|
+
hint_text: 'Connect the dots'
|
220
|
+
})
|
221
|
+
```
|
222
|
+
|
223
|
+
### Rotate
|
224
|
+
Этот метод может быть использован для решения капчи, которая просит повернуть объект. В основном используется для обхода FunCaptcha. Он возвращает угол поворота.
|
225
|
+
```ruby
|
226
|
+
result = client.rotate({
|
227
|
+
image: 'path/to/captcha.jpg',
|
228
|
+
angle: 40,
|
229
|
+
lang: 'en',
|
230
|
+
hint_image: 'path/to/hint.jpg',
|
231
|
+
hint_text: 'Put the images in the correct way'
|
232
|
+
})
|
233
|
+
```
|
234
|
+
|
235
|
+
### Lemin Cropped Captcha
|
236
|
+
Используйте этот метод для решения задания hCaptcha. Он возвращает JSON-ответ с указанными значениями: ответ (answer) и идентификатор задания (challenge_id).
|
237
|
+
```ruby
|
238
|
+
result = client.lemin({
|
239
|
+
captcha_id: 'CROPPED_1abcd2f_a1234b567c890d12ef3a456bc78d901d',
|
240
|
+
div_id: 'lemin-cropped-captcha',
|
241
|
+
pageurl: 'https://www.site.com/page/',
|
242
|
+
api_server: "https://api.leminnow.com/"
|
243
|
+
})
|
244
|
+
```
|
245
|
+
|
246
|
+
### Cloudflare Turnstile
|
247
|
+
Используйте этот метод для решения задачи Cloudflare Turnstile. Он возвращает JSON с токеном.
|
248
|
+
```ruby
|
249
|
+
result = client.turnstile({
|
250
|
+
sitekey: '0x1AAAAAAAAkg0s2VIOD34y5',
|
251
|
+
pageurl: 'http://mysite.com/'
|
252
|
+
})
|
253
|
+
```
|
254
|
+
|
255
|
+
### Amazon WAF
|
256
|
+
Используйте этот метод для решения Captcha Amazon WAF, также известного как AWS WAF Captcha, который является частью интеллектуальной защиты от угроз для Amazon AWS. Он возвращает JSON с токеном.
|
257
|
+
```ruby
|
258
|
+
result = client.amazon_waf({
|
259
|
+
sitekey: '0x1AAAAAAAAkg0s2VIOD34y5',
|
260
|
+
iv: 'CgAHbCe2GgAAAAAj',
|
261
|
+
context: '9BUgmlm48F92WUoqv97a49ZuEJJ50TCk9MVr3C7WMtQ0X6flVbufM4n8mjFLmbLVAPgaQ1Jydeaja94iAS49ljb+sUNLoukWedAQZKrlY4RdbOOzvcFqmD/ZepQFS9N5w15Exr4VwnVq+HIxTsDJwRviElWCdzKDebN/mk8/eX2n7qJi5G3Riq0tdQw9+C4diFZU5E97RSeahejOAAJTDqduqW6uLw9NsjJBkDRBlRjxjn5CaMMo5pYOxYbGrM8Un1JH5DMOLeXbq1xWbC17YSEoM1cRFfTgOoc+VpCe36Ai9Kc=',
|
262
|
+
pageurl: 'https://non-existent-example.execute-api.us-east-1.amazonaws.com/latest',
|
263
|
+
challenge_script: "https://41bcdd4fb3cb.610cd090.us-east-1.token.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/challenge.js",
|
264
|
+
captcha_script: "https://41bcdd4fb3cb.610cd090.us-east-1.captcha.awswaf.com/41bcdd4fb3cb/0d21de737ccb/cd77baa6c832/captcha.js"
|
265
|
+
})
|
266
|
+
```
|
267
|
+
|
268
|
+
### GeeTest v4
|
269
|
+
Используйте этот метод для решения GeeTest v4. Он возвращает ответ в формате JSON.
|
270
|
+
```ruby
|
271
|
+
result = client.geetest_v4({
|
272
|
+
captcha_id: 'e392e1d7fd421dc63325744d5a2b9c73',
|
273
|
+
pageurl: 'https://www.site.com/page/'
|
274
|
+
})
|
275
|
+
```
|
276
|
+
|
277
|
+
### Audio
|
278
|
+
Этот метод можно использовать для решения аудио-капчи.
|
279
|
+
```ruby
|
280
|
+
result = client.audio({
|
281
|
+
audio: 'path/to/audio.jpg',
|
282
|
+
lang: "en"
|
283
|
+
})
|
284
|
+
```
|
285
|
+
|
286
|
+
## Другие методы
|
287
|
+
|
288
|
+
### send / get_result
|
289
|
+
Эти методы могут быть использованы для ручного отправления капчи и получения результата.
|
290
|
+
```ruby
|
291
|
+
# пример для обычной капчи
|
292
|
+
captcha_id = client.send('path/to/captcha.jpg')
|
293
|
+
|
294
|
+
# или для любой другой капчи
|
295
|
+
captcha_id = client.send({
|
296
|
+
method:"lemin",
|
297
|
+
captcha_id: "CROPPED_3dfdd5c_d1872b526b794d83ba3b365eb15a200b",
|
298
|
+
api_server: "api.leminnow.com",
|
299
|
+
div_id: "lemin-cropped-captcha",
|
300
|
+
pageurl: "https://www.site.com/page/"
|
301
|
+
})
|
302
|
+
|
303
|
+
time.sleep(20)
|
304
|
+
|
305
|
+
# Получить готовый результат
|
306
|
+
result = client.get_result(captcha_id)
|
307
|
+
```
|
308
|
+
|
309
|
+
### Баланс
|
310
|
+
Используйте этот метод, чтобы посмотреть баланс в вашем аккаунте.
|
311
|
+
```ruby
|
312
|
+
balance = client.get_balance
|
313
|
+
```
|
314
|
+
|
315
|
+
### Отчет
|
316
|
+
Используйте этот метод для отправки отчета о правильном или неправильном ответе на капчу.
|
317
|
+
```ruby
|
318
|
+
client.report(captcha_id, True) # капча решена правильно
|
319
|
+
client.report(captcha_id, False) # капча решена неправильно
|
320
|
+
```
|
321
|
+
|
322
|
+
### Обработка ошибок
|
323
|
+
В случае ошибки при решении капчи генерируется исключение. Важно правильно обрабатывать такие случаи. Мы рекомендуем использовать конструкцию `begin rescue` для обработки.
|
324
|
+
```ruby
|
325
|
+
begin
|
326
|
+
result = client.text('Если завтра суббота, то какой сегодня день?')
|
327
|
+
rescue Api2Captcha::ValidationException => e
|
328
|
+
# переданы недопустимые параметры
|
329
|
+
puts(e)
|
330
|
+
rescue Api2Captcha::NetworkException => e
|
331
|
+
# возникла сетевая ошибка
|
332
|
+
puts(e)
|
333
|
+
rescue Api2Captcha::ApiException => e
|
334
|
+
# ошибка ответа от API
|
335
|
+
puts(e)
|
336
|
+
rescue Api2Captcha::TimeoutException => e
|
337
|
+
# капча до сих пор не решена
|
338
|
+
puts(e)
|
339
|
+
end
|
340
|
+
```
|
data/lib/api_2captcha/client.rb
CHANGED
@@ -5,273 +5,279 @@ require 'json'
|
|
5
5
|
require 'base64'
|
6
6
|
require 'open-uri'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
8
|
+
module Api2Captcha
|
9
|
+
class Client
|
10
|
+
DEFAULT_DOMAIN = "2captcha.com"
|
11
|
+
BASE_URL_FORMAT = "https://%s"
|
12
|
+
|
13
|
+
attr_reader :api_key, :soft_id
|
14
|
+
|
15
|
+
attr_accessor :domain, :callback,
|
16
|
+
:default_timeout,
|
17
|
+
:recaptcha_timeout,
|
18
|
+
:polling_interval
|
19
|
+
|
20
|
+
def initialize(api_key, soft_id = 0, callback = nil)
|
21
|
+
@api_key = api_key
|
22
|
+
@soft_id = soft_id
|
23
|
+
@callback = callback
|
24
|
+
@default_timeout = 120
|
25
|
+
@recaptcha_timeout = 600
|
26
|
+
@polling_interval = 10
|
27
|
+
@domain = DEFAULT_DOMAIN
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
if @callback
|
35
|
-
params["pingback"] = @callback
|
36
|
-
return_id = true
|
37
|
-
else
|
38
|
-
return_id
|
39
|
-
end
|
40
|
-
complete_params = get_params(params)
|
41
|
-
captcha_id = send_request(complete_params)
|
42
|
-
|
43
|
-
return_id ? captcha_id : get_result(captcha_id)
|
44
|
-
end
|
30
|
+
def solve(method, params = {}, file_path = nil, return_id: false)
|
31
|
+
params["method"] = method
|
32
|
+
params["key"] = @api_key
|
33
|
+
params["soft_id"] = @soft_id
|
34
|
+
params["json"] = 1
|
45
35
|
|
46
|
-
|
47
|
-
|
48
|
-
|
36
|
+
if @callback
|
37
|
+
params["pingback"] = @callback
|
38
|
+
return_id = true
|
39
|
+
end
|
49
40
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
method = arg.delete(:method) || "POST"
|
55
|
-
solve(method, arg, return_id: true)
|
56
|
-
else
|
57
|
-
raise ArgumentError, "Invalid arguments of the send method"
|
41
|
+
complete_params = get_params(params)
|
42
|
+
captcha_id = send_request(complete_params)
|
43
|
+
return captcha_id if return_id
|
44
|
+
get_result(captcha_id)
|
58
45
|
end
|
59
|
-
end
|
60
46
|
|
61
|
-
|
62
|
-
|
63
|
-
|
47
|
+
def send(*args)
|
48
|
+
raise ArgumentError,
|
49
|
+
"Invalid arguments of the send method" unless args.size == 1
|
64
50
|
|
65
|
-
|
66
|
-
|
51
|
+
arg = args.first
|
52
|
+
if arg.is_a?(String)
|
53
|
+
solve("POST", {}, arg, return_id: true)
|
54
|
+
elsif arg.is_a?(Hash)
|
55
|
+
method = arg.delete(:method) || "POST"
|
56
|
+
solve(method, arg, return_id: true)
|
57
|
+
else
|
58
|
+
raise ArgumentError, "Invalid arguments of the send method"
|
59
|
+
end
|
60
|
+
end
|
67
61
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
62
|
+
def get_result(captcha_id)
|
63
|
+
uri = URI("#{base_url}/res.php?key=#{@api_key}&action=get&id=#{captcha_id}&json=1")
|
64
|
+
start_time = Time.now
|
65
|
+
|
66
|
+
loop do
|
67
|
+
response = make_request(uri)
|
68
|
+
|
69
|
+
case response
|
70
|
+
when Net::HTTPSuccess
|
71
|
+
response_json = JSON.parse(response.body)
|
72
|
+
if response_json["status"] == 1
|
73
|
+
return response_json["request"]
|
74
|
+
elsif response_json["request"] == "CAPCHA_NOT_READY"
|
75
|
+
sleep(polling_interval)
|
76
|
+
else
|
77
|
+
raise ApiException, "API Error: #{response_json["request"]}"
|
78
|
+
end
|
75
79
|
else
|
76
|
-
raise
|
80
|
+
raise NetworkException, "Network Error: #{response.code.to_i}"
|
77
81
|
end
|
78
|
-
|
79
|
-
raise
|
82
|
+
|
83
|
+
raise TimeoutException, "Timeout" if Time.now - start_time > default_timeout
|
80
84
|
end
|
85
|
+
end
|
81
86
|
|
82
|
-
|
87
|
+
def report(captcha_id, is_correct)
|
88
|
+
report = is_correct ? "reportgood" : "reportbad"
|
89
|
+
uri = URI("#{base_url}/res.php?key=#{@api_key}&action=#{report}&id=#{captcha_id}")
|
90
|
+
make_request(uri)
|
83
91
|
end
|
84
|
-
end
|
85
92
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
93
|
+
def get_balance
|
94
|
+
response = make_res_request({ "action" => "getbalance" }, "getbalance")
|
95
|
+
return response["request"].to_f
|
96
|
+
end
|
91
97
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
98
|
+
def normal(params)
|
99
|
+
solve("post", params)
|
100
|
+
end
|
96
101
|
|
97
|
-
|
98
|
-
|
99
|
-
|
102
|
+
def text(params)
|
103
|
+
solve("textcaptcha", params)
|
104
|
+
end
|
100
105
|
|
101
|
-
|
102
|
-
|
103
|
-
|
106
|
+
def recaptcha_v2(params)
|
107
|
+
solve("userrecaptcha", params)
|
108
|
+
end
|
104
109
|
|
105
|
-
|
106
|
-
|
107
|
-
|
110
|
+
def recaptcha_v3(params)
|
111
|
+
solve("userrecaptcha", params)
|
112
|
+
end
|
108
113
|
|
109
|
-
|
110
|
-
|
111
|
-
|
114
|
+
def funcaptcha(params)
|
115
|
+
solve("funcaptcha", params)
|
116
|
+
end
|
112
117
|
|
113
|
-
|
114
|
-
|
115
|
-
|
118
|
+
def geetest(params)
|
119
|
+
solve("geetest", params)
|
120
|
+
end
|
116
121
|
|
117
|
-
|
118
|
-
|
119
|
-
|
122
|
+
def hcaptcha(params)
|
123
|
+
solve("hcaptcha", params)
|
124
|
+
end
|
120
125
|
|
121
|
-
|
122
|
-
|
123
|
-
|
126
|
+
def keycaptcha(params)
|
127
|
+
solve("keycaptcha", params)
|
128
|
+
end
|
124
129
|
|
125
|
-
|
126
|
-
|
127
|
-
|
130
|
+
def capy(params)
|
131
|
+
solve("capy", params)
|
132
|
+
end
|
128
133
|
|
129
|
-
|
130
|
-
|
131
|
-
|
134
|
+
def grid(params)
|
135
|
+
params["recaptcha"] = 1
|
136
|
+
solve("post", params)
|
137
|
+
end
|
132
138
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
139
|
+
def canvas(params)
|
140
|
+
params["recaptcha"] = 1
|
141
|
+
params["canvas"] = 1
|
142
|
+
solve("post", params)
|
143
|
+
end
|
137
144
|
|
138
|
-
|
139
|
-
|
140
|
-
params["canvas"] = 1
|
141
|
-
solve("post", params)
|
142
|
-
end
|
145
|
+
def coordinates(params)
|
146
|
+
params["coordinatescaptcha"] = 1
|
143
147
|
|
144
|
-
|
145
|
-
|
148
|
+
solve("post", params)
|
149
|
+
end
|
146
150
|
|
147
|
-
|
148
|
-
|
151
|
+
def rotate(params)
|
152
|
+
solve("rotatecaptcha", params)
|
153
|
+
end
|
149
154
|
|
150
|
-
|
151
|
-
|
152
|
-
|
155
|
+
def geetest_v4(params)
|
156
|
+
solve("geetest_v4", params)
|
157
|
+
end
|
153
158
|
|
154
|
-
|
155
|
-
|
156
|
-
|
159
|
+
def lemin(params)
|
160
|
+
solve("lemin", params)
|
161
|
+
end
|
157
162
|
|
158
|
-
|
159
|
-
|
160
|
-
|
163
|
+
def turnstile(params)
|
164
|
+
solve("turnstile", params)
|
165
|
+
end
|
161
166
|
|
162
|
-
|
163
|
-
|
164
|
-
|
167
|
+
def amazon_waf(params)
|
168
|
+
solve("amazon_waf", params)
|
169
|
+
end
|
165
170
|
|
166
|
-
|
167
|
-
|
168
|
-
|
171
|
+
def audio(params)
|
172
|
+
audio = params.delete(:audio)
|
173
|
+
audio_content = File.file?(audio) ? File.binread(audio) : audio
|
169
174
|
|
170
|
-
|
171
|
-
|
172
|
-
|
175
|
+
params = params.merge(
|
176
|
+
"body" => Base64.strict_encode64(audio_content),
|
177
|
+
"lang" => params[:lang]
|
178
|
+
)
|
179
|
+
solve("audio", params)
|
180
|
+
end
|
173
181
|
|
174
|
-
|
175
|
-
"
|
176
|
-
|
177
|
-
)
|
178
|
-
solve("audio", params)
|
179
|
-
end
|
182
|
+
def yandex(params)
|
183
|
+
solve("yandex", params)
|
184
|
+
end
|
180
185
|
|
181
|
-
|
186
|
+
private
|
182
187
|
|
183
|
-
|
184
|
-
|
185
|
-
|
188
|
+
def base_url
|
189
|
+
BASE_URL_FORMAT % @domain
|
190
|
+
end
|
186
191
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
192
|
+
def send_request(params)
|
193
|
+
uri = URI("#{base_url}/in.php")
|
194
|
+
req = Net::HTTP::Post.new(uri)
|
195
|
+
req.content_type = 'application/json'
|
196
|
+
req.body = params.to_json
|
197
|
+
captcha_id = get_captcha_id(make_request(uri, req))
|
198
|
+
end
|
194
199
|
|
195
|
-
|
196
|
-
|
197
|
-
|
200
|
+
def get_params(params)
|
201
|
+
params[:image].nil? ? params : file_params(params)
|
202
|
+
end
|
198
203
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
204
|
+
def file_params(params)
|
205
|
+
image = params.delete(:image)
|
206
|
+
hint_image = params.delete(:hint_image)
|
207
|
+
|
208
|
+
image_content = get_image_content(image)
|
209
|
+
hint_image_content = get_image_content(hint_image) if hint_image
|
210
|
+
result_params = {
|
211
|
+
"method" => "base64",
|
212
|
+
"body" => Base64.strict_encode64(image_content),
|
213
|
+
"filename" => File.basename(image),
|
214
|
+
"ext" => File.extname(image).delete(".")
|
215
|
+
}
|
216
|
+
|
217
|
+
result_params["imginstructions"] = Base64.strict_encode64(hint_image_content) if hint_image_content
|
218
|
+
params.merge(result_params)
|
219
|
+
end
|
215
220
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
+
def get_image_content(image)
|
222
|
+
return download_image(image) if image.start_with?('http')
|
223
|
+
return File.binread(image) if File.file?(image)
|
224
|
+
image
|
225
|
+
end
|
221
226
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
227
|
+
def download_image(url)
|
228
|
+
response = URI.open(url)
|
229
|
+
if response.status[0] != '200'
|
230
|
+
raise StandardError, "File could not be downloaded from url: #{url}"
|
231
|
+
end
|
232
|
+
response.read
|
226
233
|
end
|
227
|
-
response.read
|
228
|
-
end
|
229
234
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
+
def handle_response(captcha_id)
|
236
|
+
captcha_result = get_result(captcha_id) if @callback.nil?
|
237
|
+
@callback&.call(captcha_id)
|
238
|
+
captcha_result
|
239
|
+
end
|
235
240
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
241
|
+
def get_captcha_id(response)
|
242
|
+
case response
|
243
|
+
when Net::HTTPSuccess
|
244
|
+
response_json = JSON.parse(response.body.strip)
|
245
|
+
if response_json["status"] == 1
|
246
|
+
response_json["request"]
|
247
|
+
else
|
248
|
+
raise ApiException, "API Error: #{response_json["error_text"]}"
|
249
|
+
end
|
242
250
|
else
|
243
|
-
raise
|
251
|
+
raise NetworkException, "Network Error: #{response.code.to_i}"
|
244
252
|
end
|
245
|
-
|
246
|
-
raise
|
253
|
+
rescue JSON::ParserError => e
|
254
|
+
raise "Failed to parse response: #{e.message}"
|
247
255
|
end
|
248
|
-
rescue JSON::ParserError => e
|
249
|
-
raise "Failed to parse response: #{e.message}"
|
250
|
-
end
|
251
256
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
257
|
+
def make_request(uri, req = nil)
|
258
|
+
if req.nil?
|
259
|
+
Net::HTTP.get_response(uri)
|
260
|
+
else
|
261
|
+
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
262
|
+
http.request(req)
|
263
|
+
end
|
258
264
|
end
|
259
265
|
end
|
260
|
-
end
|
261
266
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
+
def make_res_request(request, action)
|
268
|
+
uri = URI("#{base_url}/res.php?key=#{@api_key}&action=#{action}&json=1")
|
269
|
+
req = Net::HTTP::Post.new(uri)
|
270
|
+
req.content_type = 'application/json'
|
271
|
+
req.body = request.to_json
|
267
272
|
|
268
|
-
|
273
|
+
response = make_request(uri, req)
|
269
274
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
+
case response
|
276
|
+
when Net::HTTPSuccess
|
277
|
+
return JSON.parse(response.body)
|
278
|
+
else
|
279
|
+
raise Api2Captcha::NetworkException, "Network Error: #{response.code.to_i}"
|
280
|
+
end
|
275
281
|
end
|
276
282
|
end
|
277
283
|
end
|
data/lib/api_2captcha/version.rb
CHANGED
data/lib/api_2captcha.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'api_2captcha/api2captcha_exceptions'
|
4
|
+
require_relative 'api_2captcha/client'
|
5
|
+
require_relative 'api_2captcha/version'
|
4
6
|
|
5
7
|
module Api2Captcha
|
6
|
-
require_relative 'api_2captcha/api2captcha_exceptions'
|
7
8
|
def self.new(*args)
|
8
9
|
Client.new(*args)
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
12
|
-
require 'api_2captcha/client'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-2captcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 2captcha.com
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Ruby package for easy integration with the API of 2captcha captcha solving
|
14
14
|
service to bypass recaptcha, hcaptcha, funcaptcha, geetest and solve any other captchas.
|
@@ -26,6 +26,7 @@ files:
|
|
26
26
|
- Gemfile.lock
|
27
27
|
- LICENSE
|
28
28
|
- README.md
|
29
|
+
- README.ru.md
|
29
30
|
- Rakefile
|
30
31
|
- api_2captcha.gemspec
|
31
32
|
- lib/api_2captcha.rb
|
@@ -56,7 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
57
|
- !ruby/object:Gem::Version
|
57
58
|
version: '0'
|
58
59
|
requirements: []
|
59
|
-
rubygems_version: 3.
|
60
|
+
rubygems_version: 3.0.1
|
60
61
|
signing_key:
|
61
62
|
specification_version: 4
|
62
63
|
summary: 2Captcha API wrapper for Ruby.
|