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 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)