anti_captcha 2.0.0 → 2.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 +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)
|