solvecaptcha-ruby 1.0.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 +7 -0
- data/CODE_OF_CONDUCT.md +43 -0
- data/CONTRIBUTING.md +72 -0
- data/Gemfile +14 -0
- data/LICENSE +21 -0
- data/README.md +640 -0
- data/RELEASING.md +16 -0
- data/Rakefile +12 -0
- data/api_solvecaptcha.gemspec +39 -0
- data/examples/amazon_waf_example.rb +7 -0
- data/examples/atb_captcha_example.rb +11 -0
- data/examples/audio_example.rb +10 -0
- data/examples/canvas_example.rb +7 -0
- data/examples/capy_example.rb +7 -0
- data/examples/clickcaptcha_example.rb +7 -0
- data/examples/cutcaptcha_example.rb +7 -0
- data/examples/cybersiara_example.rb +7 -0
- data/examples/datadome_example.rb +7 -0
- data/examples/friendlycaptcha_example.rb +7 -0
- data/examples/funcaptcha_example.rb +7 -0
- data/examples/geetest_example.rb +7 -0
- data/examples/geetest_v4_example.rb +7 -0
- data/examples/grid_captcha_example.rb +14 -0
- data/examples/hcaptcha_example.rb +10 -0
- data/examples/keycaptcha_example.rb +7 -0
- data/examples/lemin_example.rb +7 -0
- data/examples/media/example.mp3 +0 -0
- data/examples/media/normal_2.jpg +0 -0
- data/examples/media/recaptchaGrid4x4.jpg +0 -0
- data/examples/media/recaptchaGridImginstructions4x4.jpg +0 -0
- data/examples/mtcaptcha_example.rb +7 -0
- data/examples/normal_captcha_example.rb +15 -0
- data/examples/recaptcha_enterprise_example.rb +7 -0
- data/examples/recaptcha_v2_example.rb +10 -0
- data/examples/recaptcha_v3_example.rb +7 -0
- data/examples/rotate_example.rb +7 -0
- data/examples/tencent_example.rb +10 -0
- data/examples/turnstile_example.rb +7 -0
- data/examples/yandex_smart_example.rb +7 -0
- data/lib/api_solvecaptcha/api_solvecaptcha_exceptions.rb +25 -0
- data/lib/api_solvecaptcha/client.rb +166 -0
- data/lib/api_solvecaptcha/version.rb +5 -0
- data/lib/api_solvecaptcha.rb +13 -0
- metadata +93 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/api_solvecaptcha/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "solvecaptcha-ruby"
|
7
|
+
spec.version = ApiSolveCaptcha::VERSION
|
8
|
+
spec.authors = ["solvecaptcha.com"]
|
9
|
+
|
10
|
+
spec.summary = "Solvercaptcha API wrapper for Ruby."
|
11
|
+
spec.description = "Ruby package for easy integration with the API of solvecaptcha captcha solving service to bypass recaptcha, funcaptcha, geetest and solve any other captchas."
|
12
|
+
spec.homepage = "https://solvecaptcha.com//"
|
13
|
+
spec.license = "MIT"
|
14
|
+
spec.required_ruby_version = ">= 2.6.0"
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["source_code_uri"] = "https://github.com/solvercaptcha/solvecaptcha-ruby"
|
18
|
+
spec.metadata["changelog_uri"] = "https://github.com/solvercaptcha/solvecaptcha-ruby/releases"
|
19
|
+
spec.metadata["github_repo"] = "ssh://github.com/solvercaptcha/solvecaptcha-ruby"
|
20
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/solvercaptcha/solvecaptcha-ruby/issues"
|
21
|
+
spec.metadata["keywords"] = "Solvercaptcha, captcha solver, captcha bypass, Ruby, automation, CAPTCHA API, CAPTCHA recognition, anti-captcha, reCAPTCHA, OCR, image recognition, human verification, bot protection, recaptcha"
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(__dir__) do
|
26
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
(File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
spec.bindir = "bin"
|
31
|
+
spec.executables = spec.files.grep(%r{\Abin/}) { |f| File.basename(f) }
|
32
|
+
spec.require_paths = ["lib"]
|
33
|
+
|
34
|
+
# Uncomment to register a new dependency of your gem
|
35
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
36
|
+
|
37
|
+
# For more information and examples about making a new gem, check out our
|
38
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
39
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative '../lib/api_solvecaptcha'
|
2
|
+
|
3
|
+
client = ApiSolveCaptcha.new("YOUR_API_KEY")
|
4
|
+
|
5
|
+
result = client.atb_captcha({
|
6
|
+
app_id: "197326679",
|
7
|
+
api_server: "api.atb_captcha.com",
|
8
|
+
pageurl: "https://mysite.com/page/with/atb_captcha"
|
9
|
+
})
|
10
|
+
|
11
|
+
puts "Result: #{result.inspect}"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative '../lib/api_solvecaptcha'
|
2
|
+
|
3
|
+
client = ApiSolveCaptcha.new("YOUR_API_KEY")
|
4
|
+
|
5
|
+
result = client.grid({
|
6
|
+
image: './media/recaptchaGrid4x4.jpg',
|
7
|
+
rows: 4,
|
8
|
+
cols: 4,
|
9
|
+
lang: 'en',
|
10
|
+
hint_image: './media/recaptchaGridImginstructions4x4.jpg',
|
11
|
+
# hint_text: 'Select all squares with stairs'
|
12
|
+
})
|
13
|
+
|
14
|
+
puts "Result: #{result.inspect}"
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require_relative '../lib/api_solvecaptcha'
|
2
|
+
|
3
|
+
client = ApiSolveCaptcha::Client.new('YOUR_API_KEY')
|
4
|
+
|
5
|
+
result = client.keycaptcha({'s_s_c_user_id': 'USER_ID', 's_s_c_session_id': 'SESSION_ID', 's_s_c_web_server_sign': 'SIGN', 's_s_c_web_server_sign2': 'SIGN2', 'pageurl': 'https://example.com'})
|
6
|
+
|
7
|
+
puts result
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative "../lib/api_solvecaptcha"
|
2
|
+
|
3
|
+
client = ApiSolveCaptcha.new("YOUR_API_KEY")
|
4
|
+
|
5
|
+
image_path = File.join(__dir__, 'media', 'normal_2.jpg')
|
6
|
+
|
7
|
+
puts "Image path: #{image_path}"
|
8
|
+
puts "File exists: #{File.exist?(image_path)}"
|
9
|
+
puts "File size: #{File.size?(image_path).to_i} bytes"
|
10
|
+
|
11
|
+
result = client.normal({
|
12
|
+
image: image_path,
|
13
|
+
})
|
14
|
+
|
15
|
+
puts "Result: #{result.inspect}"
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative "../lib/api_solvecaptcha"
|
2
|
+
|
3
|
+
client = ApiSolveCaptcha.new("6663f112abc465058b7a9b448d3a0f54")
|
4
|
+
|
5
|
+
result = client.recaptcha_v2({
|
6
|
+
googlekey: '6LfD3PIbAAAAAJs_eEHvoOl75_83eXSqpPSRFJ_u',
|
7
|
+
pageurl: 'https://solvecaptcha.com/demo/recaptcha-v2',
|
8
|
+
})
|
9
|
+
|
10
|
+
puts "Result: #{result.inspect}"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ApiSolveCaptcha
|
2
|
+
class ValidationException < StandardError
|
3
|
+
def initialize(message = 'Invalid parameters passed')
|
4
|
+
super(message)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class NetworkException < StandardError
|
9
|
+
def initialize(message = 'Network error occurred')
|
10
|
+
super(message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ApiException < StandardError
|
15
|
+
def initialize(message = 'API response error')
|
16
|
+
super(message)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class TimeoutException < StandardError
|
21
|
+
def initialize(message = 'Captcha solving timed out')
|
22
|
+
super(message)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
require 'base64'
|
5
|
+
require 'open-uri'
|
6
|
+
require 'net/http/post/multipart'
|
7
|
+
|
8
|
+
|
9
|
+
module ApiSolveCaptcha
|
10
|
+
class Client
|
11
|
+
DEFAULT_DOMAIN = "api.solvecaptcha.com"
|
12
|
+
BASE_URL_FORMAT = "https://%s"
|
13
|
+
|
14
|
+
attr_accessor :domain, :callback, :default_timeout,
|
15
|
+
:soft_id, :recaptcha_timeout,
|
16
|
+
:polling_interval, :api_key
|
17
|
+
|
18
|
+
def initialize(api_key, callback = nil)
|
19
|
+
@api_key = api_key
|
20
|
+
@soft_id = nil
|
21
|
+
@callback = callback
|
22
|
+
@default_timeout = 120
|
23
|
+
@recaptcha_timeout = 600
|
24
|
+
@polling_interval = 5
|
25
|
+
@domain = DEFAULT_DOMAIN
|
26
|
+
end
|
27
|
+
|
28
|
+
def solve(method, return_id: false, **params)
|
29
|
+
params["method"] = method
|
30
|
+
params["key"] = @api_key
|
31
|
+
params["json"] = 1
|
32
|
+
|
33
|
+
params["pingback"] = @callback if @callback
|
34
|
+
|
35
|
+
complete_params = get_params(params)
|
36
|
+
captcha_id = send_request(complete_params)
|
37
|
+
return captcha_id if return_id
|
38
|
+
|
39
|
+
get_result(captcha_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def normal(params)
|
43
|
+
solve("post", **params)
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_result(captcha_id)
|
47
|
+
uri = URI("#{base_url}/res.php?key=#{@api_key}&action=get&id=#{captcha_id}&json=1")
|
48
|
+
start_time = Time.now
|
49
|
+
|
50
|
+
loop do
|
51
|
+
response = make_request(uri)
|
52
|
+
|
53
|
+
if response.is_a?(Net::HTTPSuccess)
|
54
|
+
response_json = JSON.parse(response.body.strip)
|
55
|
+
|
56
|
+
case response_json["request"]
|
57
|
+
when "CAPCHA_NOT_READY"
|
58
|
+
sleep @polling_interval
|
59
|
+
when /[a-zA-Z0-9]+/
|
60
|
+
return response_json
|
61
|
+
else
|
62
|
+
raise "API Error: #{response_json["request"]}"
|
63
|
+
end
|
64
|
+
else
|
65
|
+
raise "Network Error: #{response.code}"
|
66
|
+
end
|
67
|
+
|
68
|
+
raise "Timeout" if Time.now - start_time > @default_timeout
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def report(captcha_id, is_correct)
|
73
|
+
action = is_correct ? "reportgood" : "reportbad"
|
74
|
+
uri = URI("#{base_url}/res.php?key=#{@api_key}&action=#{action}&id=#{captcha_id}")
|
75
|
+
make_request(uri)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def base_url
|
81
|
+
BASE_URL_FORMAT % @domain
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_params(params)
|
85
|
+
params["image"].nil? ? params : file_params(params)
|
86
|
+
end
|
87
|
+
|
88
|
+
def file_params(params)
|
89
|
+
image = params.delete("image")
|
90
|
+
hint_image = params.delete("hint_image")
|
91
|
+
|
92
|
+
image_content = if base64_encoded?(image)
|
93
|
+
image
|
94
|
+
else
|
95
|
+
Base64.strict_encode64(get_image_content(image))
|
96
|
+
end
|
97
|
+
|
98
|
+
hint_image_content = if hint_image
|
99
|
+
base64_encoded?(hint_image) ? hint_image : Base64.strict_encode64(get_image_content(hint_image))
|
100
|
+
end
|
101
|
+
|
102
|
+
result_params = {
|
103
|
+
"method" => "base64",
|
104
|
+
"body" => image_content,
|
105
|
+
"filename" => File.basename(image),
|
106
|
+
"ext" => File.extname(image).delete(".")
|
107
|
+
}
|
108
|
+
|
109
|
+
result_params["imginstructions"] = hint_image_content if hint_image_content
|
110
|
+
params.merge(result_params)
|
111
|
+
end
|
112
|
+
|
113
|
+
def get_image_content(image)
|
114
|
+
return download_image(image) if image.start_with?('http')
|
115
|
+
return File.binread(image) if File.file?(image)
|
116
|
+
image
|
117
|
+
end
|
118
|
+
|
119
|
+
def base64_encoded?(string)
|
120
|
+
string.is_a?(String) && string.match(/\A[A-Za-z0-9+\/=]+\z/) && (string.length % 4).zero?
|
121
|
+
end
|
122
|
+
|
123
|
+
def download_image(url)
|
124
|
+
response = URI.open(url)
|
125
|
+
if response.status[0] != '200'
|
126
|
+
raise StandardError, "File could not be downloaded from url: #{url}"
|
127
|
+
end
|
128
|
+
response.read
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
def send_request(params)
|
133
|
+
uri = URI("#{base_url}/in.php")
|
134
|
+
|
135
|
+
file_path = params.delete("image")
|
136
|
+
file = UploadIO.new(File.open(file_path), mime_type(file_path), File.basename(file_path))
|
137
|
+
|
138
|
+
form_data = params.merge("file" => file)
|
139
|
+
|
140
|
+
req = Net::HTTP::Post::Multipart.new(uri.path, form_data)
|
141
|
+
|
142
|
+
response = make_request(uri, req)
|
143
|
+
|
144
|
+
if response.is_a?(Net::HTTPSuccess)
|
145
|
+
parsed_response = JSON.parse(response.body.strip)
|
146
|
+
|
147
|
+
raise "API Error: #{parsed_response["request"]}" unless parsed_response["status"] == 1
|
148
|
+
|
149
|
+
parsed_response["request"]
|
150
|
+
else
|
151
|
+
raise "Network Error: #{response.code}"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def mime_type(file_path)
|
156
|
+
MIME::Types.type_for(file_path).first.to_s || "application/octet-stream"
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
def make_request(uri, req = nil)
|
161
|
+
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
162
|
+
http.request(req || Net::HTTP::Get.new(uri))
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./api_solvecaptcha/api_solvecaptcha_exceptions"
|
4
|
+
require_relative "./api_solvecaptcha/client"
|
5
|
+
require_relative "./api_solvecaptcha/version"
|
6
|
+
|
7
|
+
|
8
|
+
module ApiSolveCaptcha
|
9
|
+
def self.new(*args)
|
10
|
+
Client.new(*args)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: solvecaptcha-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- solvecaptcha.com
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-04-22 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Ruby package for easy integration with the API of solvecaptcha captcha
|
14
|
+
solving service to bypass recaptcha, funcaptcha, geetest and solve any other captchas.
|
15
|
+
email:
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- CODE_OF_CONDUCT.md
|
21
|
+
- CONTRIBUTING.md
|
22
|
+
- Gemfile
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
- RELEASING.md
|
26
|
+
- Rakefile
|
27
|
+
- api_solvecaptcha.gemspec
|
28
|
+
- examples/amazon_waf_example.rb
|
29
|
+
- examples/atb_captcha_example.rb
|
30
|
+
- examples/audio_example.rb
|
31
|
+
- examples/canvas_example.rb
|
32
|
+
- examples/capy_example.rb
|
33
|
+
- examples/clickcaptcha_example.rb
|
34
|
+
- examples/cutcaptcha_example.rb
|
35
|
+
- examples/cybersiara_example.rb
|
36
|
+
- examples/datadome_example.rb
|
37
|
+
- examples/friendlycaptcha_example.rb
|
38
|
+
- examples/funcaptcha_example.rb
|
39
|
+
- examples/geetest_example.rb
|
40
|
+
- examples/geetest_v4_example.rb
|
41
|
+
- examples/grid_captcha_example.rb
|
42
|
+
- examples/hcaptcha_example.rb
|
43
|
+
- examples/keycaptcha_example.rb
|
44
|
+
- examples/lemin_example.rb
|
45
|
+
- examples/media/example.mp3
|
46
|
+
- examples/media/normal_2.jpg
|
47
|
+
- examples/media/recaptchaGrid4x4.jpg
|
48
|
+
- examples/media/recaptchaGridImginstructions4x4.jpg
|
49
|
+
- examples/mtcaptcha_example.rb
|
50
|
+
- examples/normal_captcha_example.rb
|
51
|
+
- examples/recaptcha_enterprise_example.rb
|
52
|
+
- examples/recaptcha_v2_example.rb
|
53
|
+
- examples/recaptcha_v3_example.rb
|
54
|
+
- examples/rotate_example.rb
|
55
|
+
- examples/tencent_example.rb
|
56
|
+
- examples/turnstile_example.rb
|
57
|
+
- examples/yandex_smart_example.rb
|
58
|
+
- lib/api_solvecaptcha.rb
|
59
|
+
- lib/api_solvecaptcha/api_solvecaptcha_exceptions.rb
|
60
|
+
- lib/api_solvecaptcha/client.rb
|
61
|
+
- lib/api_solvecaptcha/version.rb
|
62
|
+
homepage: https://solvecaptcha.com//
|
63
|
+
licenses:
|
64
|
+
- MIT
|
65
|
+
metadata:
|
66
|
+
homepage_uri: https://solvecaptcha.com//
|
67
|
+
source_code_uri: https://github.com/solvercaptcha/solvecaptcha-ruby
|
68
|
+
changelog_uri: https://github.com/solvercaptcha/solvecaptcha-ruby/releases
|
69
|
+
github_repo: ssh://github.com/solvercaptcha/solvecaptcha-ruby
|
70
|
+
bug_tracker_uri: https://github.com/solvercaptcha/solvecaptcha-ruby/issues
|
71
|
+
keywords: Solvercaptcha, captcha solver, captcha bypass, Ruby, automation, CAPTCHA
|
72
|
+
API, CAPTCHA recognition, anti-captcha, reCAPTCHA, OCR, image recognition, human
|
73
|
+
verification, bot protection, recaptcha
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.6.0
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubygems_version: 3.4.19
|
90
|
+
signing_key:
|
91
|
+
specification_version: 4
|
92
|
+
summary: Solvercaptcha API wrapper for Ruby.
|
93
|
+
test_files: []
|