anticaptchaofficial 1.0.1

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.
@@ -0,0 +1,318 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anticaptcha
4
+ # Builds the "task" objects sent to the createTask API method.
5
+ #
6
+ # Every method validates what it can before anything leaves the process and
7
+ # raises {InvalidTaskError} on bad input. You normally do not call these
8
+ # directly, {Client} does it for you.
9
+ module Tasks
10
+ module_function
11
+
12
+ PROXY_TYPES = %w[http socks4 socks5].freeze
13
+
14
+ # Validates your proxy and turns it into the API's proxy* fields.
15
+ #
16
+ # @param proxy [Hash] :type, :address, :port, :login, :password
17
+ # @param with_type [Boolean] AntiBotCookieTask takes no proxyType
18
+ def proxy_fields(proxy, with_type: true)
19
+ raise InvalidTaskError, "proxy is required for a proxy-on task" if proxy.nil?
20
+
21
+ proxy = normalize(proxy)
22
+ address = proxy[:address].to_s
23
+ port = proxy[:port].to_i
24
+ type = (proxy[:type] || "http").to_s
25
+
26
+ raise InvalidTaskError, "proxy address is empty" if address.empty?
27
+ unless (1..65_535).cover?(port)
28
+ raise InvalidTaskError,
29
+ "proxy port #{proxy[:port].inspect} is out of range"
30
+ end
31
+
32
+ unless PROXY_TYPES.include?(type)
33
+ raise InvalidTaskError, "proxy type must be one of #{PROXY_TYPES.join(", ")}, got #{type.inspect}"
34
+ end
35
+
36
+ fields = { "proxyAddress" => address, "proxyPort" => port }
37
+ fields["proxyType"] = type if with_type
38
+
39
+ login = proxy[:login].to_s
40
+
41
+ unless login.empty?
42
+ fields["proxyLogin"] = login
43
+ fields["proxyPassword"] = proxy[:password].to_s
44
+ end
45
+
46
+ fields
47
+ end
48
+
49
+ # https://anti-captcha.com/apidoc/task-types/ImageToTextTask
50
+ def image(body:, phrase: false, case_sensitive: false, numeric: 0, math_operation: false,
51
+ min_length: 0, max_length: 0, language_pool: "en", comment: nil, website_url: nil)
52
+ raise InvalidTaskError, "captcha image is empty" if body.to_s.empty?
53
+
54
+ task = {
55
+ "type" => "ImageToTextTask",
56
+ "body" => body,
57
+ "phrase" => phrase,
58
+ "case" => case_sensitive,
59
+ "numeric" => numeric,
60
+ "math" => math_operation,
61
+ "minLength" => min_length,
62
+ "maxLength" => max_length,
63
+ "languagePool" => language_pool
64
+ }
65
+
66
+ put(task, "comment", comment)
67
+ put(task, "websiteURL", website_url)
68
+
69
+ task
70
+ end
71
+
72
+ # https://anti-captcha.com/apidoc/task-types/ImageToCoordinatesTask
73
+ def image_to_coordinates(body:, mode: "points", comment: nil, website_url: nil)
74
+ raise InvalidTaskError, "captcha image is empty" if body.to_s.empty?
75
+
76
+ task = { "type" => "ImageToCoordinatesTask", "body" => body, "mode" => mode }
77
+
78
+ put(task, "comment", comment)
79
+ put(task, "websiteURL", website_url)
80
+
81
+ task
82
+ end
83
+
84
+ # https://anti-captcha.com/apidoc/task-types/RecaptchaV2TaskProxyless
85
+ #
86
+ # Setting is_enterprise switches the task to RecaptchaV2EnterpriseTask.
87
+ # Enterprise tasks get isInvisible only when it is true.
88
+ def recaptcha_v2(website_url:, website_key:, website_s_token: nil, is_invisible: false,
89
+ data_s_value: nil, is_enterprise: false, enterprise_payload: nil,
90
+ api_domain: nil, user_agent: nil, proxy: nil)
91
+ type =
92
+ if is_enterprise
93
+ proxy ? "RecaptchaV2EnterpriseTask" : "RecaptchaV2EnterpriseTaskProxyless"
94
+ else
95
+ proxy ? "RecaptchaV2Task" : "RecaptchaV2TaskProxyless"
96
+ end
97
+
98
+ task = {
99
+ "type" => type,
100
+ "websiteURL" => website_url,
101
+ "websiteKey" => website_key
102
+ }
103
+
104
+ task["isInvisible"] = is_invisible if !is_enterprise || is_invisible
105
+ put(task, "websiteSToken", website_s_token)
106
+ put(task, "recaptchaDataSValue", data_s_value)
107
+ put(task, "apiDomain", api_domain)
108
+ put(task, "enterprisePayload", enterprise_payload)
109
+
110
+ with_proxy(task, proxy, user_agent)
111
+ end
112
+
113
+ # https://anti-captcha.com/apidoc/task-types/RecaptchaV3TaskProxyless
114
+ # This captcha has no proxy-on version.
115
+ def recaptcha_v3(website_url:, website_key:, min_score: 0.3, page_action: nil,
116
+ is_enterprise: false, api_domain: nil)
117
+ unless [0.3, 0.7, 0.9].include?(min_score)
118
+ raise InvalidTaskError, "min_score must be one of 0.3, 0.7, 0.9; got #{min_score.inspect}"
119
+ end
120
+
121
+ task = {
122
+ "type" => "RecaptchaV3TaskProxyless",
123
+ "websiteURL" => website_url,
124
+ "websiteKey" => website_key,
125
+ "minScore" => min_score,
126
+ "isEnterprise" => is_enterprise
127
+ }
128
+
129
+ put(task, "pageAction", page_action)
130
+ put(task, "apiDomain", api_domain)
131
+
132
+ task
133
+ end
134
+
135
+ # https://anti-captcha.com/apidoc/task-types/HCaptchaTaskProxyless
136
+ def hcaptcha(website_url:, website_key:, is_invisible: false, is_enterprise: false,
137
+ enterprise_payload: nil, user_agent: nil, cookies: nil, proxy: nil)
138
+ task = {
139
+ "type" => proxy ? "HCaptchaTask" : "HCaptchaTaskProxyless",
140
+ "websiteURL" => website_url,
141
+ "websiteKey" => website_key,
142
+ "isInvisible" => is_invisible,
143
+ "isEnterprise" => is_enterprise
144
+ }
145
+
146
+ put(task, "enterprisePayload", enterprise_payload)
147
+ task = with_proxy(task, proxy, user_agent)
148
+ put(task, "cookies", cookies) if proxy
149
+
150
+ task
151
+ end
152
+
153
+ # https://anti-captcha.com/apidoc/task-types/FunCaptchaTaskProxyless
154
+ def funcaptcha(website_url:, website_public_key:, api_subdomain: nil, data_blob: nil,
155
+ user_agent: nil, proxy: nil)
156
+ task = {
157
+ "type" => proxy ? "FunCaptchaTask" : "FunCaptchaTaskProxyless",
158
+ "websiteURL" => website_url,
159
+ "websitePublicKey" => website_public_key
160
+ }
161
+
162
+ put(task, "funcaptchaApiJSSubdomain", api_subdomain)
163
+ put(task, "data", data_blob)
164
+
165
+ with_proxy(task, proxy, user_agent)
166
+ end
167
+
168
+ # https://anti-captcha.com/apidoc/task-types/GeeTestTaskProxyless
169
+ def geetest(website_url:, gt:, version: 3, challenge: nil, api_subdomain: nil,
170
+ init_parameters: nil, user_agent: nil, proxy: nil)
171
+ unless [3, 4].include?(version)
172
+ raise InvalidTaskError, "GeeTest version must be 3 or 4, got #{version.inspect}"
173
+ end
174
+
175
+ raise InvalidTaskError, "GeeTest v3 requires a challenge value" if version == 3 && challenge.to_s.empty?
176
+
177
+ task = {
178
+ "type" => proxy ? "GeeTestTask" : "GeeTestTaskProxyless",
179
+ "websiteURL" => website_url,
180
+ "gt" => gt,
181
+ "version" => version
182
+ }
183
+
184
+ put(task, "challenge", challenge)
185
+ put(task, "geetestApiServerSubdomain", api_subdomain)
186
+ put(task, "initParameters", init_parameters)
187
+
188
+ with_proxy(task, proxy, user_agent)
189
+ end
190
+
191
+ # https://anti-captcha.com/apidoc/task-types/TurnstileTaskProxyless
192
+ def turnstile(website_url:, website_key:, action: nil, c_data: nil, chl_page_data: nil,
193
+ user_agent: nil, proxy: nil)
194
+ task = {
195
+ "type" => proxy ? "TurnstileTask" : "TurnstileTaskProxyless",
196
+ "websiteURL" => website_url,
197
+ "websiteKey" => website_key
198
+ }
199
+
200
+ put(task, "action", action)
201
+ put(task, "cData", c_data)
202
+ put(task, "chlPageData", chl_page_data)
203
+
204
+ with_proxy(task, proxy, user_agent)
205
+ end
206
+
207
+ # https://anti-captcha.com/apidoc/task-types/ProsopoTaskProxyless
208
+ def prosopo(website_url:, website_key:, user_agent: nil, proxy: nil)
209
+ sitekey_task(proxy ? "ProsopoTask" : "ProsopoTaskProxyless",
210
+ website_url, website_key, user_agent, proxy)
211
+ end
212
+
213
+ # https://anti-captcha.com/apidoc/task-types/FriendlyCaptchaTaskProxyless
214
+ def friendly_captcha(website_url:, website_key:, user_agent: nil, proxy: nil)
215
+ sitekey_task(proxy ? "FriendlyCaptchaTask" : "FriendlyCaptchaTaskProxyless",
216
+ website_url, website_key, user_agent, proxy)
217
+ end
218
+
219
+ # https://anti-captcha.com/apidoc/task-types/AltchaTaskProxyless
220
+ def altcha(website_url:, challenge_url: nil, challenge_json: nil, user_agent: nil, proxy: nil)
221
+ if challenge_url.to_s.empty? && challenge_json.to_s.empty?
222
+ raise InvalidTaskError, "set either challenge_url or challenge_json"
223
+ end
224
+
225
+ task = {
226
+ "type" => proxy ? "AltchaTask" : "AltchaTaskProxyless",
227
+ "websiteURL" => website_url
228
+ }
229
+
230
+ put(task, "challengeURL", challenge_url)
231
+ put(task, "challengeJSON", challenge_json)
232
+
233
+ with_proxy(task, proxy, user_agent)
234
+ end
235
+
236
+ # https://anti-captcha.com/apidoc/task-types/AmazonTaskProxyless
237
+ def amazon(website_url:, website_key:, iv: nil, context: nil, captcha_script: nil,
238
+ challenge_script: nil, jsapi_script: nil, waf_type: nil, user_agent: nil,
239
+ proxy: nil)
240
+ task = {
241
+ "type" => proxy ? "AmazonTask" : "AmazonTaskProxyless",
242
+ "websiteURL" => website_url,
243
+ "websiteKey" => website_key
244
+ }
245
+
246
+ put(task, "wafType", waf_type)
247
+ put(task, "iv", iv)
248
+ put(task, "context", context)
249
+ put(task, "captchaScript", captcha_script)
250
+ put(task, "challengeScript", challenge_script)
251
+ put(task, "jsapiScript", jsapi_script)
252
+
253
+ with_proxy(task, proxy, user_agent)
254
+ end
255
+
256
+ # https://anti-captcha.com/apidoc/task-types/AntiGateTask
257
+ #
258
+ # The proxy is optional for this task type.
259
+ def antigate(website_url:, template_name:, variables: nil, domains_of_interest: nil,
260
+ proxy: nil)
261
+ task = {
262
+ "type" => "AntiGateTask",
263
+ "websiteURL" => website_url,
264
+ "templateName" => template_name
265
+ }
266
+
267
+ put(task, "variables", variables)
268
+ put(task, "domainsOfInterest", domains_of_interest)
269
+
270
+ task.merge!(proxy_fields(proxy)) if proxy
271
+
272
+ task
273
+ end
274
+
275
+ # https://anti-captcha.com/apidoc/task-types/AntiBotCookieTask
276
+ #
277
+ # The proxy is required: the cookies are only valid for the IP address they
278
+ # were issued to. This task type takes no proxyType, only http proxies work.
279
+ def antibot_cookie(website_url:, proxy:)
280
+ {
281
+ "type" => "AntiBotCookieTask",
282
+ "websiteURL" => website_url
283
+ }.merge(proxy_fields(proxy, with_type: false))
284
+ end
285
+
286
+ # Prosopo and Friendly Captcha take exactly the same parameters.
287
+ def sitekey_task(type, website_url, website_key, user_agent, proxy)
288
+ task = { "type" => type, "websiteURL" => website_url, "websiteKey" => website_key }
289
+
290
+ with_proxy(task, proxy, user_agent)
291
+ end
292
+
293
+ # Adds a parameter, skipping it when the caller left it unset.
294
+ def put(task, name, value)
295
+ return task if value.nil?
296
+ return task if value.respond_to?(:empty?) && value.empty?
297
+
298
+ task[name] = value
299
+ task
300
+ end
301
+
302
+ def with_proxy(task, proxy, user_agent)
303
+ return task if proxy.nil?
304
+
305
+ task.merge!(proxy_fields(proxy))
306
+ put(task, "userAgent", user_agent)
307
+
308
+ task
309
+ end
310
+
311
+ # Accepts both symbol and string keys.
312
+ def normalize(proxy)
313
+ return proxy if proxy.is_a?(Hash) && proxy.keys.all?(Symbol)
314
+
315
+ proxy.to_h { |key, value| [key.to_sym, value] }
316
+ end
317
+ end
318
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anticaptcha
4
+ VERSION = "1.0.1"
5
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "anticaptcha/version"
4
+ require_relative "anticaptcha/errors"
5
+ require_relative "anticaptcha/solution"
6
+ require_relative "anticaptcha/tasks"
7
+ require_relative "anticaptcha/client"
8
+
9
+ # Official Anti-Captcha.com API client.
10
+ #
11
+ # Solves image captchas, Recaptcha v2/v3 (Enterprise and non-Enterprise),
12
+ # hCaptcha, FunCaptcha (Arkose Labs), GeeTest v3/v4, Cloudflare Turnstile,
13
+ # Amazon WAF, Prosopo, Friendly Captcha, Altcha, and runs AntiGate custom
14
+ # scenarios.
15
+ #
16
+ # require "anticaptcha"
17
+ #
18
+ # client = Anticaptcha.new("API_KEY_HERE")
19
+ # puts client.balance
20
+ #
21
+ # solution = client.solve_recaptcha_v2(
22
+ # website_url: "https://www.website.com/",
23
+ # website_key: "6Lcyu8UZAAAAACwSh6Xf58WrNXTu0LLu4F85xf20"
24
+ # )
25
+ # puts solution.g_recaptcha_response
26
+ #
27
+ # See https://anti-captcha.com/apidoc for the API details.
28
+ module Anticaptcha
29
+ # Shorthand for Anticaptcha::Client.new.
30
+ def self.new(api_key = nil, **options)
31
+ Client.new(api_key, **options)
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: anticaptchaofficial
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Anti-Captcha.com
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: |-
13
+ Official Anti-Captcha.com client for solving image captchas, Recaptcha V2/V3
14
+ (Enterprise and non-Enterprise), hCaptcha, FunCaptcha (Arkose Labs), GeeTest
15
+ v3/v4, Cloudflare Turnstile, Amazon WAF, Prosopo, Friendly Captcha, Altcha
16
+ and AntiGate custom tasks. No runtime dependencies.
17
+ email:
18
+ - support@anti-captcha.com
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - LICENSE
24
+ - README.md
25
+ - lib/anticaptcha.rb
26
+ - lib/anticaptcha/client.rb
27
+ - lib/anticaptcha/errors.rb
28
+ - lib/anticaptcha/solution.rb
29
+ - lib/anticaptcha/tasks.rb
30
+ - lib/anticaptcha/version.rb
31
+ homepage: https://anti-captcha.com
32
+ licenses:
33
+ - MIT
34
+ metadata:
35
+ homepage_uri: https://anti-captcha.com
36
+ source_code_uri: https://github.com/anti-captcha/anticaptcha-ruby
37
+ documentation_uri: https://anti-captcha.com/apidoc
38
+ bug_tracker_uri: https://github.com/anti-captcha/anticaptcha-ruby/issues
39
+ rubygems_mfa_required: 'true'
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 3.0.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 4.0.16
55
+ specification_version: 4
56
+ summary: Official Anti-Captcha.com API client
57
+ test_files: []