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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ea4b4a53f966ab69db9ea92a2575ee32afe55c88
4
- data.tar.gz: 13674c466b8c24af5b4e1e995b56151fff45d1a4
2
+ SHA256:
3
+ metadata.gz: c824ede49ec41b2b6ff994fbb8b3caae33f935e78daa10759537d44b59c37a5f
4
+ data.tar.gz: b043e76306535964664fdab5e80a51ee63743be47c2900d810769c9332ec77df
5
5
  SHA512:
6
- metadata.gz: d6fa39db3ce217ed087511f235f0a6af458cdc78899f5b3e51c886064e64eb9ad7087a61c1e007b36d5600a13b7ece8b89738e1bf4591ffe2d7ca92d66d1899a
7
- data.tar.gz: 7d3b40a511221ddd807698b06c55b13e98ec10b3dcf48284266444bb43aca3a38f1f39a9976db68295d14f3d53164936b3ff7985f10e743e4a55f907295db1a8
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'
@@ -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
- if task['taskId']
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
- started_at = Time.now
138
-
139
- if proxy.nil?
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
- # @option options [String] :proxy_type
208
- # @option options [String] :proxy_address
209
- # @option options [String] :proxy_port
210
- # @option options [String] :proxy_login
211
- # @option options [String] :proxy_login
212
- # @option options [String] :proxy_password
213
- # @option options [String] :user_agent
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 'NoCaptchaTaskProxyless'
199
+ when 'NoCaptchaTask'
237
200
  args[:task] = {
238
- type: 'NoCaptchaTaskProxyless',
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 'NoCaptchaTask'
206
+ when 'FunCaptchaTask'
244
207
  args[:task] = {
245
- type: 'NoCaptchaTask',
246
- websiteURL: options[:website_url],
247
- websiteKey: options[:website_key],
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
- "#{%w(ImageToTextTask NoCaptchaTaskProxyless NoCaptchaTask).join(', ')}"
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
- args = { taskId: task_id }
274
- request('getTaskResult', args)
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
  #
@@ -3,7 +3,7 @@ module AntiCaptcha
3
3
  # This is the base AntiCaptcha exception class. Rescue it if you want to
4
4
  # catch any exception that might be raised.
5
5
  #
6
- class Error < Exception
6
+ class Error < StandardError
7
7
  end
8
8
 
9
9
  class ArgumentError < Error
@@ -0,0 +1,13 @@
1
+ module AntiCaptcha
2
+ class FunCaptchaSolution < AntiCaptcha::Solution
3
+ attr_accessor :token
4
+
5
+ def initialize(task_result = nil)
6
+ super
7
+
8
+ if task_result
9
+ @token = task_result.api_result['solution']['token']
10
+ end
11
+ end
12
+ end
13
+ end
@@ -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,5 +1,12 @@
1
1
  module AntiCaptcha
2
2
  class Solution < AntiCaptcha::Model
3
3
  attr_accessor :api_response, :task_result
4
+
5
+ def initialize(task_result = nil)
6
+ if task_result
7
+ @api_response = task_result.api_result
8
+ @task_result = task_result
9
+ end
10
+ end
4
11
  end
5
12
  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
@@ -1,4 +1,4 @@
1
1
  module AntiCaptcha
2
- VERSION = "2.0.0"
2
+ VERSION = "2.1.0"
3
3
  USER_AGENT = "AntiCaptcha/Ruby v#{VERSION}"
4
4
  end
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.0.0
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: 2017-09-25 00:00:00.000000000 Z
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.5.1
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)