ruby-2captcha 1.0.3 → 1.1.0
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/.ruby-version +1 -1
- data/README.md +1 -2
- data/README.ru.md +3 -1
- data/lib/api_2captcha/client.rb +221 -217
- data/lib/api_2captcha/version.rb +1 -1
- data/lib/api_2captcha.rb +3 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d80f00729bbf9f6f08867c59bb5d6e078dbe7675dc14a0b7dd65922ab640663c
|
4
|
+
data.tar.gz: b8dd22428eab71d775a7d597bd42d661f8ded8cd1b94f30c7c54be507ea5a769
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36f2d745961278c462b64b2cccbc30b6fee82b67e0b4f768f8068babb1c9af5b8e675b88089ad7c81afa33321f288749ac808d01f23966a50c498a70dea4aeac
|
7
|
+
data.tar.gz: f91c2ec90c7d09edf188c47b9718bf4152f508f808146b965a3be0e8fa69dbf661cc70df9b8634ff760bcdf54d79d44873119abf09bb353f494203139b670c02
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.6.0
|
data/README.md
CHANGED
@@ -34,7 +34,6 @@ A Ruby client for the 2Captcha API.
|
|
34
34
|
- [Error handling](#error-handling)
|
35
35
|
|
36
36
|
## Installation
|
37
|
-
|
38
37
|
Add this line to your application's Gemfile:
|
39
38
|
|
40
39
|
```bash
|
@@ -56,7 +55,7 @@ $ gem install ruby-2captcha
|
|
56
55
|
To use the api2captcha gem, you'll need to import the module and create a Client instance. Here's an example:
|
57
56
|
|
58
57
|
```ruby
|
59
|
-
require '
|
58
|
+
require 'api_2captcha'
|
60
59
|
|
61
60
|
client = Api2Captcha.new("YOUR_API_KEY")
|
62
61
|
```
|
data/README.ru.md
CHANGED
@@ -32,7 +32,6 @@ Ruby-клиент для API 2Captcha.
|
|
32
32
|
- [Обработка ошибок](#error-handling)
|
33
33
|
|
34
34
|
## Установка
|
35
|
-
|
36
35
|
Автоматическая установка гема с помощью Bundler. Добавьте следующую строку в ваш Gemfile:
|
37
36
|
```ruby
|
38
37
|
gem 'ruby-2captcha'
|
@@ -54,7 +53,10 @@ gem install ruby-2captcha
|
|
54
53
|
Описание всех необходимых параметров для настройки установленного гема.
|
55
54
|
|
56
55
|
Экземпляр класса Api2Captcha можно создать следующим образом:
|
56
|
+
|
57
57
|
```ruby
|
58
|
+
require 'api_2captcha'
|
59
|
+
|
58
60
|
client = Api2Captcha.new("YOUR_API_KEY")
|
59
61
|
```
|
60
62
|
|
data/lib/api_2captcha/client.rb
CHANGED
@@ -5,277 +5,281 @@ 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
|
-
|
28
|
-
|
29
|
-
def solve(method, params = {}, file_path = nil, return_id: false)
|
30
|
-
params["method"] = method
|
31
|
-
params["key"] = @api_key
|
32
|
-
params["soft_id"] = @soft_id
|
33
|
-
params["json"] = 1
|
34
|
-
|
35
|
-
if @callback
|
36
|
-
params["pingback"] = @callback
|
37
|
-
return_id = true
|
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
|
38
28
|
end
|
39
29
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
30
|
+
def solve(method, file_path = nil, return_id: false, **params)
|
31
|
+
params = params.transform_keys(&:to_s)
|
32
|
+
params["method"] = method
|
33
|
+
params["key"] = @api_key
|
34
|
+
params["soft_id"] = @soft_id
|
35
|
+
params["json"] = 1
|
45
36
|
|
46
|
-
|
47
|
-
|
48
|
-
|
37
|
+
if @callback
|
38
|
+
params["pingback"] = @callback
|
39
|
+
return_id = true
|
40
|
+
end
|
49
41
|
|
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"
|
42
|
+
complete_params = get_params(params)
|
43
|
+
captcha_id = send_request(complete_params)
|
44
|
+
return captcha_id if return_id
|
45
|
+
get_result(captcha_id)
|
58
46
|
end
|
59
|
-
end
|
60
47
|
|
61
|
-
|
62
|
-
|
63
|
-
|
48
|
+
def send(*args)
|
49
|
+
raise ArgumentError,
|
50
|
+
"Invalid arguments of the send method" unless args.size == 1
|
64
51
|
|
65
|
-
|
66
|
-
|
52
|
+
arg = args.first
|
53
|
+
if arg.is_a?(String)
|
54
|
+
solve("POST", {}, arg, return_id: true)
|
55
|
+
elsif arg.is_a?(Hash)
|
56
|
+
method = arg.delete(:method) || "POST"
|
57
|
+
solve(method, arg, return_id: true)
|
58
|
+
else
|
59
|
+
raise ArgumentError, "Invalid arguments of the send method"
|
60
|
+
end
|
61
|
+
end
|
67
62
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
63
|
+
def get_result(captcha_id)
|
64
|
+
uri = URI("#{base_url}/res.php?key=#{@api_key}&action=get&id=#{captcha_id}&json=1")
|
65
|
+
start_time = Time.now
|
66
|
+
|
67
|
+
loop do
|
68
|
+
response = make_request(uri)
|
69
|
+
|
70
|
+
case response
|
71
|
+
when Net::HTTPSuccess
|
72
|
+
response_json = JSON.parse(response.body)
|
73
|
+
if response_json["status"] == 1
|
74
|
+
response_json["captcha_id"] = captcha_id
|
75
|
+
return response_json
|
76
|
+
elsif response_json["request"] == "CAPCHA_NOT_READY"
|
77
|
+
sleep(polling_interval)
|
78
|
+
else
|
79
|
+
raise ApiException, "API Error: #{response_json["request"]}"
|
80
|
+
end
|
75
81
|
else
|
76
|
-
raise
|
82
|
+
raise NetworkException, "Network Error: #{response.code.to_i}"
|
77
83
|
end
|
78
|
-
else
|
79
|
-
raise NetworkException, "Network Error: #{response.code.to_i}"
|
80
|
-
end
|
81
84
|
|
82
|
-
|
85
|
+
raise TimeoutException, "Timeout" if Time.now - start_time > default_timeout
|
86
|
+
end
|
83
87
|
end
|
84
|
-
end
|
85
88
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
89
|
+
def report(captcha_id, is_correct)
|
90
|
+
report = is_correct ? "reportgood" : "reportbad"
|
91
|
+
uri = URI("#{base_url}/res.php?key=#{@api_key}&action=#{report}&id=#{captcha_id}")
|
92
|
+
make_request(uri)
|
93
|
+
end
|
91
94
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
95
|
+
def get_balance
|
96
|
+
response = make_res_request({ "action" => "getbalance" }, "getbalance")
|
97
|
+
return response["request"].to_f
|
98
|
+
end
|
96
99
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
+
def normal(params)
|
101
|
+
solve("post", params)
|
102
|
+
end
|
100
103
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
+
def text(params)
|
105
|
+
solve("textcaptcha", params)
|
106
|
+
end
|
104
107
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
+
def recaptcha_v2(params)
|
109
|
+
solve("userrecaptcha", params)
|
110
|
+
end
|
108
111
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
+
def recaptcha_v3(params)
|
113
|
+
solve("userrecaptcha", params)
|
114
|
+
end
|
112
115
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
+
def funcaptcha(params)
|
117
|
+
solve("funcaptcha", params)
|
118
|
+
end
|
116
119
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
+
def geetest(params)
|
121
|
+
solve("geetest", params)
|
122
|
+
end
|
120
123
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
+
def hcaptcha(params)
|
125
|
+
solve("hcaptcha", params)
|
126
|
+
end
|
124
127
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
+
def keycaptcha(params)
|
129
|
+
solve("keycaptcha", params)
|
130
|
+
end
|
128
131
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
+
def capy(params)
|
133
|
+
solve("capy", params)
|
134
|
+
end
|
132
135
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
136
|
+
def grid(params)
|
137
|
+
params["recaptcha"] = 1
|
138
|
+
solve("post", params)
|
139
|
+
end
|
137
140
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
141
|
+
def canvas(params)
|
142
|
+
params["recaptcha"] = 1
|
143
|
+
params["canvas"] = 1
|
144
|
+
solve("post", params)
|
145
|
+
end
|
143
146
|
|
144
|
-
|
145
|
-
|
147
|
+
def coordinates(params)
|
148
|
+
params["coordinatescaptcha"] = 1
|
146
149
|
|
147
|
-
|
148
|
-
|
150
|
+
solve("post", params)
|
151
|
+
end
|
149
152
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
+
def rotate(params)
|
154
|
+
solve("rotatecaptcha", params)
|
155
|
+
end
|
153
156
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
+
def geetest_v4(params)
|
158
|
+
solve("geetest_v4", params)
|
159
|
+
end
|
157
160
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
+
def lemin(params)
|
162
|
+
solve("lemin", params)
|
163
|
+
end
|
161
164
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
+
def turnstile(params)
|
166
|
+
solve("turnstile", params)
|
167
|
+
end
|
165
168
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
+
def amazon_waf(params)
|
170
|
+
solve("amazon_waf", params)
|
171
|
+
end
|
169
172
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
+
def audio(params)
|
174
|
+
audio = params.delete("audio")
|
175
|
+
audio_content = File.file?(audio) ? File.binread(audio) : audio
|
173
176
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
177
|
+
params = params.merge(
|
178
|
+
"body" => Base64.strict_encode64(audio_content),
|
179
|
+
"lang" => params["lang"]
|
180
|
+
)
|
181
|
+
solve("audio", params)
|
182
|
+
end
|
180
183
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
+
def yandex(params)
|
185
|
+
solve("yandex", params)
|
186
|
+
end
|
184
187
|
|
185
|
-
|
188
|
+
private
|
186
189
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
+
def base_url
|
191
|
+
BASE_URL_FORMAT % @domain
|
192
|
+
end
|
190
193
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
194
|
+
def send_request(params)
|
195
|
+
uri = URI("#{base_url}/in.php")
|
196
|
+
req = Net::HTTP::Post.new(uri)
|
197
|
+
req.content_type = 'application/json'
|
198
|
+
req.body = params.to_json
|
199
|
+
captcha_id = get_captcha_id(make_request(uri, req))
|
200
|
+
end
|
198
201
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
+
def get_params(params)
|
203
|
+
params["image"].nil? ? params : file_params(params)
|
204
|
+
end
|
202
205
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
206
|
+
def file_params(params)
|
207
|
+
image = params.delete("image")
|
208
|
+
hint_image = params.delete("hint_image")
|
209
|
+
|
210
|
+
image_content = get_image_content(image)
|
211
|
+
hint_image_content = get_image_content(hint_image) if hint_image
|
212
|
+
result_params = {
|
213
|
+
"method" => "base64",
|
214
|
+
"body" => Base64.strict_encode64(image_content),
|
215
|
+
"filename" => File.basename(image),
|
216
|
+
"ext" => File.extname(image).delete(".")
|
217
|
+
}
|
218
|
+
|
219
|
+
result_params["imginstructions"] = Base64.strict_encode64(hint_image_content) if hint_image_content
|
220
|
+
params.merge(result_params)
|
221
|
+
end
|
219
222
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
223
|
+
def get_image_content(image)
|
224
|
+
return download_image(image) if image.start_with?('http')
|
225
|
+
return File.binread(image) if File.file?(image)
|
226
|
+
image
|
227
|
+
end
|
225
228
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
229
|
+
def download_image(url)
|
230
|
+
response = URI.open(url)
|
231
|
+
if response.status[0] != '200'
|
232
|
+
raise StandardError, "File could not be downloaded from url: #{url}"
|
233
|
+
end
|
234
|
+
response.read
|
230
235
|
end
|
231
|
-
response.read
|
232
|
-
end
|
233
236
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
237
|
+
def handle_response(captcha_id)
|
238
|
+
captcha_result = get_result(captcha_id) if @callback.nil?
|
239
|
+
@callback&.call(captcha_id)
|
240
|
+
captcha_result
|
241
|
+
end
|
239
242
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
243
|
+
def get_captcha_id(response)
|
244
|
+
case response
|
245
|
+
when Net::HTTPSuccess
|
246
|
+
response_json = JSON.parse(response.body.strip)
|
247
|
+
if response_json["status"] == 1
|
248
|
+
response_json["request"]
|
249
|
+
else
|
250
|
+
raise ApiException, "API Error: #{response_json["request"]}"
|
251
|
+
end
|
246
252
|
else
|
247
|
-
raise
|
253
|
+
raise NetworkException, "Network Error: #{response.code.to_i}"
|
248
254
|
end
|
249
|
-
|
250
|
-
raise
|
255
|
+
rescue JSON::ParserError => e
|
256
|
+
raise "Failed to parse response: #{e.message}"
|
251
257
|
end
|
252
|
-
rescue JSON::ParserError => e
|
253
|
-
raise "Failed to parse response: #{e.message}"
|
254
|
-
end
|
255
258
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
259
|
+
def make_request(uri, req = nil)
|
260
|
+
if req.nil?
|
261
|
+
Net::HTTP.get_response(uri)
|
262
|
+
else
|
263
|
+
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
264
|
+
http.request(req)
|
265
|
+
end
|
262
266
|
end
|
263
267
|
end
|
264
|
-
end
|
265
268
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
269
|
+
def make_res_request(request, action)
|
270
|
+
uri = URI("#{base_url}/res.php?key=#{@api_key}&action=#{action}&json=1")
|
271
|
+
req = Net::HTTP::Post.new(uri)
|
272
|
+
req.content_type = 'application/json'
|
273
|
+
req.body = request.to_json
|
271
274
|
|
272
|
-
|
275
|
+
response = make_request(uri, req)
|
273
276
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
277
|
+
case response
|
278
|
+
when Net::HTTPSuccess
|
279
|
+
return JSON.parse(response.body)
|
280
|
+
else
|
281
|
+
raise Api2Captcha::NetworkException, "Network Error: #{response.code.to_i}"
|
282
|
+
end
|
279
283
|
end
|
280
284
|
end
|
281
285
|
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.1.0
|
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-04 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.
|
@@ -57,7 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
57
|
- !ruby/object:Gem::Version
|
58
58
|
version: '0'
|
59
59
|
requirements: []
|
60
|
-
rubygems_version: 3.
|
60
|
+
rubygems_version: 3.0.1
|
61
61
|
signing_key:
|
62
62
|
specification_version: 4
|
63
63
|
summary: 2Captcha API wrapper for Ruby.
|