anti_captcha 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +20 -0
- data/lib/anti_captcha.rb +1 -0
- data/lib/anti_captcha/client.rb +88 -104
- data/lib/anti_captcha/errors.rb +1 -1
- data/lib/anti_captcha/models/fun_captcha_solution.rb +13 -0
- data/lib/anti_captcha/models/image_to_text_solution.rb +9 -0
- data/lib/anti_captcha/models/no_captcha_solution.rb +9 -0
- data/lib/anti_captcha/models/solution.rb +7 -0
- data/lib/anti_captcha/models/task_result.rb +16 -1
- data/lib/anti_captcha/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c824ede49ec41b2b6ff994fbb8b3caae33f935e78daa10759537d44b59c37a5f
|
4
|
+
data.tar.gz: b043e76306535964664fdab5e80a51ee63743be47c2900d810769c9332ec77df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0894512b1baaf7bf6b53bcdee0c34c25fdad188c3ce499194aefb68beae30ec360ad47e059fb54dffdb2da3fe9629706021155f78bf7319f83c4dcb0e6b01e6
|
7
|
+
data.tar.gz: b51249b061d7a8a85c0909cece6b6f7f07cc7c4c25bc8ae2826197ca24e28f89b93302d2497663b78ebdfb2e5ff1c47f1e19bcbd2649c51b359118c4080f085f
|
data/README.md
CHANGED
@@ -115,6 +115,26 @@ Or install it yourself as:
|
|
115
115
|
"1JJHJ_VuuHAqJKxcaasbTsqw-L1Sm4gD57PTeaEr9-MaETG1vfu2H5zlcwkjsRoZoHxx6V9yUDw8Ig-hYD8kakmSnnjNQd50w_Y_tI3aDLp-s_7ZmhH6pcaoWWsid5hdtMXyvrP9DscDuCLBf7etLle8caPWSaYCpAq9DOTtj5NpSg6-OeCJdGdkjsakFUMeGeqmje87wSajcjmdjl_w4XZBY2zy8fUH6XoAGZ6AeCTulIljBQDObQynKDd-rutPvKNxZasDk-LbhTfw508g1lu9io6jnvm3kbAdnkfZ0x0PkGiUMHU7hnuoW6bXo2Yn_Zt5tDWL7N7wFtY6B0k7cTy73f8er508zReOuoyz2NqL8smDCmcJu05ajkPGt20qzpURMwHaw"
|
116
116
|
```
|
117
117
|
|
118
|
+
7. **FunCaptcha**
|
119
|
+
|
120
|
+
This method allows you to solve FunCaptcha.
|
121
|
+
|
122
|
+
**Send the `website_public_key` and `website_url` parameters**
|
123
|
+
|
124
|
+
This method requires no browser emulation. You can send two parameters that
|
125
|
+
identify the website in which the CAPTCHA is found.
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
options = {
|
129
|
+
website_public_key: 'xyz',
|
130
|
+
website_url: 'http://example.com/example=1',
|
131
|
+
language_pool: '...'
|
132
|
+
}
|
133
|
+
|
134
|
+
solution = client.decode_fun_captcha(options)
|
135
|
+
solution.token # Solution of the captcha
|
136
|
+
```
|
137
|
+
|
118
138
|
## Notes
|
119
139
|
|
120
140
|
#### Ruby dependencies
|
data/lib/anti_captcha.rb
CHANGED
@@ -34,6 +34,7 @@ require 'anti_captcha/errors'
|
|
34
34
|
require 'anti_captcha/models/solution'
|
35
35
|
require 'anti_captcha/models/image_to_text_solution'
|
36
36
|
require 'anti_captcha/models/no_captcha_solution'
|
37
|
+
require 'anti_captcha/models/fun_captcha_solution'
|
37
38
|
require 'anti_captcha/models/task_result'
|
38
39
|
require 'anti_captcha/client'
|
39
40
|
require 'anti_captcha/version'
|
data/lib/anti_captcha/client.rb
CHANGED
@@ -4,6 +4,8 @@ module AntiCaptcha
|
|
4
4
|
#
|
5
5
|
class Client
|
6
6
|
BASE_URL = 'https://api.anti-captcha.com/:action'
|
7
|
+
PROXYABLE_TASKS = %w(NoCaptchaTask FunCaptchaTask)
|
8
|
+
SUPPORTED_TASKS = %w(ImageToTextTask NoCaptchaTask FunCaptchaTask)
|
7
9
|
|
8
10
|
attr_accessor :client_key, :timeout, :polling
|
9
11
|
|
@@ -58,48 +60,18 @@ module AntiCaptcha
|
|
58
60
|
# answer. 0 - no requirements.
|
59
61
|
# @option options [Integer] :max_length Defines maximum length of the
|
60
62
|
# answer. 0 - no requirements.
|
63
|
+
# @option options [String] :comment Additional comment for workers like
|
64
|
+
# "enter letters in red color". Result
|
65
|
+
# is not guaranteed.
|
61
66
|
#
|
62
67
|
# @return [AntiCaptcha::ImageToTextSolution] The solution of the image
|
63
68
|
# CAPTCHA.
|
64
69
|
#
|
65
70
|
def decode_image!(options)
|
66
|
-
started_at = Time.now
|
67
|
-
|
68
71
|
options[:body64] = load_captcha(options)
|
69
72
|
task = create_task!('ImageToTextTask', options)
|
70
|
-
|
71
|
-
|
72
|
-
api_result = get_task_result!(task['taskId'])
|
73
|
-
|
74
|
-
while api_result['status'] != 'ready'
|
75
|
-
sleep(polling)
|
76
|
-
api_result = get_task_result!(task['taskId'])
|
77
|
-
raise AntiCaptcha::Timeout if (Time.now - started_at) > timeout
|
78
|
-
end
|
79
|
-
|
80
|
-
task_result = AntiCaptcha::TaskResult.new(
|
81
|
-
task_id: task['taskId'],
|
82
|
-
error_id: api_result['errorId'],
|
83
|
-
error_code: api_result['errorCode'],
|
84
|
-
error_description: api_result['errorDescription'],
|
85
|
-
status: api_result['status'],
|
86
|
-
cost: api_result['cost'],
|
87
|
-
ip: api_result['ip'],
|
88
|
-
create_time: api_result['createTime'],
|
89
|
-
end_time: api_result['endTime'],
|
90
|
-
solve_count: api_result['solveCount']
|
91
|
-
)
|
92
|
-
|
93
|
-
return AntiCaptcha::ImageToTextSolution.new(
|
94
|
-
api_response: api_result,
|
95
|
-
task_result: task_result,
|
96
|
-
url: api_result['solution']['url'],
|
97
|
-
text: api_result['solution']['text']
|
98
|
-
)
|
99
|
-
|
100
|
-
else
|
101
|
-
raise AntiCaptcha.raise_error('taskId not received from Anti Captcha.')
|
102
|
-
end
|
73
|
+
task_result = get_task_result!(task['taskId'])
|
74
|
+
AntiCaptcha::ImageToTextSolution.new(task_result)
|
103
75
|
end
|
104
76
|
|
105
77
|
#
|
@@ -134,53 +106,37 @@ module AntiCaptcha
|
|
134
106
|
# @return [AntiCaptcha::NoCaptchaSolution] The solution of the NoCaptcha.
|
135
107
|
#
|
136
108
|
def decode_nocaptcha!(options, proxy = nil)
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
task_type = 'NoCaptchaTaskProxyless'
|
141
|
-
hsh = options
|
142
|
-
else
|
143
|
-
task_type = 'NoCaptchaTask'
|
144
|
-
hsh = options.merge(proxy)
|
145
|
-
end
|
146
|
-
|
147
|
-
task = create_task!(task_type, hsh)
|
148
|
-
|
149
|
-
if task['taskId']
|
150
|
-
api_result = get_task_result!(task['taskId'])
|
151
|
-
|
152
|
-
while api_result['status'] != 'ready'
|
153
|
-
sleep(polling)
|
154
|
-
api_result = get_task_result!(task['taskId'])
|
155
|
-
raise AntiCaptcha::Timeout if (Time.now - started_at) > timeout
|
156
|
-
end
|
157
|
-
|
158
|
-
task_result = AntiCaptcha::TaskResult.new(
|
159
|
-
task_id: task['taskId'],
|
160
|
-
error_id: api_result['errorId'],
|
161
|
-
error_code: api_result['errorCode'],
|
162
|
-
error_description: api_result['errorDescription'],
|
163
|
-
status: api_result['status'],
|
164
|
-
cost: api_result['cost'],
|
165
|
-
ip: api_result['ip'],
|
166
|
-
create_time: api_result['createTime'],
|
167
|
-
end_time: api_result['endTime'],
|
168
|
-
solve_count: api_result['solveCount']
|
169
|
-
)
|
170
|
-
|
171
|
-
return AntiCaptcha::NoCaptchaSolution.new(
|
172
|
-
api_response: api_result,
|
173
|
-
task_result: task_result,
|
174
|
-
g_recaptcha_response: api_result['solution']['gRecaptchaResponse'],
|
175
|
-
g_recaptcha_response_md5: api_result['solution']['gRecaptchaResponseMD5']
|
176
|
-
)
|
177
|
-
|
178
|
-
else
|
179
|
-
raise AntiCaptcha.raise_error('taskId not received from Anti Captcha.')
|
180
|
-
end
|
109
|
+
task = create_task!('NoCaptchaTask', options, proxy)
|
110
|
+
task_result = get_task_result!(task['taskId'])
|
111
|
+
AntiCaptcha::NoCaptchaSolution.new(task_result)
|
181
112
|
end
|
182
113
|
|
183
114
|
#
|
115
|
+
# Decodes a FunCaptcha CAPTCHA.
|
116
|
+
#
|
117
|
+
# @param [Hash] options Options hash.
|
118
|
+
# @option options [String] :website_url
|
119
|
+
# @option options [String] :website_public_key
|
120
|
+
# @option options [String] :language_pool
|
121
|
+
#
|
122
|
+
# @param [Hash] proxy Not mandatory. A hash with configs of the proxy that
|
123
|
+
# has to be used. Defaults to `nil`.
|
124
|
+
# @option proxy [String] :proxy_type
|
125
|
+
# @option proxy [String] :proxy_address
|
126
|
+
# @option proxy [String] :proxy_port
|
127
|
+
# @option proxy [String] :proxy_login
|
128
|
+
# @option proxy [String] :proxy_login
|
129
|
+
# @option proxy [String] :proxy_password
|
130
|
+
# @option proxy [String] :user_agent
|
131
|
+
#
|
132
|
+
# @return [AntiCaptcha::FunCaptchaSolution] The solution of the FunCaptcha.
|
133
|
+
#
|
134
|
+
def decode_fun_captcha!(options, proxy = nil)
|
135
|
+
task = create_task!('FunCaptchaTask', options, proxy)
|
136
|
+
task_result = get_task_result!(task['taskId'])
|
137
|
+
AntiCaptcha::FunCaptchaSolution.new(task_result)
|
138
|
+
end
|
139
|
+
|
184
140
|
# Creates a task for solving the selected CAPTCHA type.
|
185
141
|
#
|
186
142
|
# @param [String] type The type of the CAPTCHA.
|
@@ -200,21 +156,27 @@ module AntiCaptcha
|
|
200
156
|
# answer. 0 - no requirements.
|
201
157
|
# @option options [Integer] :max_length Defines maximum length of the
|
202
158
|
# answer. 0 - no requirements.
|
159
|
+
# @option options [String] :comment Additional comment for workers like
|
160
|
+
# "enter letters in red color". Result
|
161
|
+
# is not guaranteed.
|
203
162
|
# # NoCaptcha
|
204
163
|
# @option options [String] :website_url Address of target web page.
|
205
164
|
# @option options [String] :website_key Recaptcha website key.
|
206
165
|
# @option options [String] :language_pool
|
207
|
-
#
|
208
|
-
#
|
209
|
-
#
|
210
|
-
# @option
|
211
|
-
# @option
|
212
|
-
# @option
|
213
|
-
# @option
|
166
|
+
#
|
167
|
+
# @param [Hash] proxy Not mandatory. A hash with configs of the proxy that
|
168
|
+
# has to be used. Defaults to `nil`.
|
169
|
+
# @option proxy [String] :proxy_type
|
170
|
+
# @option proxy [String] :proxy_address
|
171
|
+
# @option proxy [String] :proxy_port
|
172
|
+
# @option proxy [String] :proxy_login
|
173
|
+
# @option proxy [String] :proxy_login
|
174
|
+
# @option proxy [String] :proxy_password
|
175
|
+
# @option proxy [String] :user_agent
|
214
176
|
#
|
215
177
|
# @return [Hash] Information about the task.
|
216
178
|
#
|
217
|
-
def create_task!(type, options)
|
179
|
+
def create_task!(type, options, proxy = nil)
|
218
180
|
args = {
|
219
181
|
languagePool: (options[:language_pool] || 'en'),
|
220
182
|
softId: '859'
|
@@ -230,35 +192,45 @@ module AntiCaptcha
|
|
230
192
|
numeric: options[:numeric],
|
231
193
|
math: options[:math],
|
232
194
|
minLength: options[:min_length],
|
233
|
-
maxLength: options[:max_length]
|
195
|
+
maxLength: options[:max_length],
|
196
|
+
comment: options[:comment],
|
234
197
|
}
|
235
198
|
|
236
|
-
when '
|
199
|
+
when 'NoCaptchaTask'
|
237
200
|
args[:task] = {
|
238
|
-
type: '
|
201
|
+
type: 'NoCaptchaTask',
|
239
202
|
websiteURL: options[:website_url],
|
240
|
-
websiteKey: options[:website_key]
|
203
|
+
websiteKey: options[:website_key],
|
241
204
|
}
|
242
205
|
|
243
|
-
when '
|
206
|
+
when 'FunCaptchaTask'
|
244
207
|
args[:task] = {
|
245
|
-
type:
|
246
|
-
websiteURL:
|
247
|
-
|
248
|
-
proxyType: options[:proxy_type],
|
249
|
-
proxyAddress: options[:proxy_address],
|
250
|
-
proxyPort: options[:proxy_port],
|
251
|
-
proxyLogin: options[:proxy_login],
|
252
|
-
proxyPassword: options[:proxy_password],
|
253
|
-
userAgent: options[:user_agent]
|
208
|
+
type: 'FunCaptchaTask',
|
209
|
+
websiteURL: options[:website_url],
|
210
|
+
websitePublicKey: options[:website_public_key],
|
254
211
|
}
|
255
212
|
|
256
213
|
else
|
257
214
|
message = "Invalid task type: '#{type}'. Allowed types: " +
|
258
|
-
"#{
|
215
|
+
"#{SUPPORTED_TASKS.join(', ')}"
|
259
216
|
raise AntiCaptcha.raise_error(message)
|
260
217
|
end
|
261
218
|
|
219
|
+
if PROXYABLE_TASKS.include?(type)
|
220
|
+
if proxy.nil?
|
221
|
+
args[:task][:type] += 'Proxyless'
|
222
|
+
else
|
223
|
+
args.merge!(
|
224
|
+
proxyType: proxy[:proxy_type],
|
225
|
+
proxyAddress: proxy[:proxy_address],
|
226
|
+
proxyPort: proxy[:proxy_port],
|
227
|
+
proxyLogin: proxy[:proxy_login],
|
228
|
+
proxyPassword: proxy[:proxy_password],
|
229
|
+
userAgent: proxy[:user_agent]
|
230
|
+
)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
262
234
|
request('createTask', args)
|
263
235
|
end
|
264
236
|
|
@@ -270,8 +242,20 @@ module AntiCaptcha
|
|
270
242
|
# @return [Hash] Information about the task.
|
271
243
|
#
|
272
244
|
def get_task_result!(task_id)
|
273
|
-
|
274
|
-
|
245
|
+
raise AntiCaptcha.raise_error('taskId not received from Anti Captcha.') unless task_id
|
246
|
+
|
247
|
+
started_at = Time.now
|
248
|
+
|
249
|
+
loop do
|
250
|
+
api_result = request('getTaskResult', { taskId: task_id })
|
251
|
+
|
252
|
+
if api_result['status'] == 'ready'
|
253
|
+
return AntiCaptcha::TaskResult.new(api_result, task_id)
|
254
|
+
end
|
255
|
+
|
256
|
+
sleep(polling)
|
257
|
+
raise AntiCaptcha::Timeout if (Time.now - started_at) > timeout
|
258
|
+
end
|
275
259
|
end
|
276
260
|
|
277
261
|
#
|
data/lib/anti_captcha/errors.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
module AntiCaptcha
|
2
2
|
class ImageToTextSolution < AntiCaptcha::Solution
|
3
3
|
attr_accessor :url, :text
|
4
|
+
|
5
|
+
def initialize(task_result = nil)
|
6
|
+
super
|
7
|
+
|
8
|
+
if task_result
|
9
|
+
@url = task_result.api_result['solution']['url']
|
10
|
+
@text = task_result.api_result['solution']['text']
|
11
|
+
end
|
12
|
+
end
|
4
13
|
end
|
5
14
|
end
|
@@ -1,5 +1,14 @@
|
|
1
1
|
module AntiCaptcha
|
2
2
|
class NoCaptchaSolution < AntiCaptcha::Solution
|
3
3
|
attr_accessor :g_recaptcha_response, :g_recaptcha_response_md5
|
4
|
+
|
5
|
+
def initialize(task_result = nil)
|
6
|
+
super
|
7
|
+
|
8
|
+
if task_result
|
9
|
+
@g_recaptcha_response = task_result.api_result['solution']['gRecaptchaResponse']
|
10
|
+
@g_recaptcha_response_md5 = task_result.api_result['solution']['gRecaptchaResponseMD5']
|
11
|
+
end
|
12
|
+
end
|
4
13
|
end
|
5
14
|
end
|
@@ -1,6 +1,21 @@
|
|
1
1
|
module AntiCaptcha
|
2
2
|
class TaskResult < AntiCaptcha::Model
|
3
3
|
attr_accessor :task_id, :error_id, :error_code, :error_description, :status,
|
4
|
-
:cost, :ip, :create_time, :end_time, :solve_count
|
4
|
+
:cost, :ip, :create_time, :end_time, :solve_count, :api_result
|
5
|
+
|
6
|
+
def initialize(api_result, task_id)
|
7
|
+
@task_id = task_id
|
8
|
+
|
9
|
+
@api_result = api_result
|
10
|
+
@error_id = api_result['errorId']
|
11
|
+
@error_code = api_result['errorCode']
|
12
|
+
@error_description = api_result['errorDescription']
|
13
|
+
@status = api_result['status']
|
14
|
+
@cost = api_result['cost']
|
15
|
+
@ip = api_result['ip']
|
16
|
+
@create_time = api_result['createTime']
|
17
|
+
@end_time = api_result['endTime']
|
18
|
+
@solve_count = api_result['solveCount']
|
19
|
+
end
|
5
20
|
end
|
6
21
|
end
|
data/lib/anti_captcha/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anti_captcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Infosimples
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- lib/anti_captcha/client.rb
|
75
75
|
- lib/anti_captcha/errors.rb
|
76
76
|
- lib/anti_captcha/http.rb
|
77
|
+
- lib/anti_captcha/models/fun_captcha_solution.rb
|
77
78
|
- lib/anti_captcha/models/image_to_text_solution.rb
|
78
79
|
- lib/anti_captcha/models/no_captcha_solution.rb
|
79
80
|
- lib/anti_captcha/models/solution.rb
|
@@ -99,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
100
|
version: '0'
|
100
101
|
requirements: []
|
101
102
|
rubyforge_project:
|
102
|
-
rubygems_version: 2.
|
103
|
+
rubygems_version: 2.7.7
|
103
104
|
signing_key:
|
104
105
|
specification_version: 4
|
105
106
|
summary: Ruby API for Anti Captcha (CAPTCHA Solver as a Service)
|