zero_captcha 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/.gitignore +12 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +140 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/zero_captcha.rb +32 -0
- data/lib/zero_captcha/client.rb +142 -0
- data/lib/zero_captcha/errors.rb +52 -0
- data/lib/zero_captcha/http.rb +119 -0
- data/lib/zero_captcha/models/captcha.rb +18 -0
- data/lib/zero_captcha/version.rb +5 -0
- data/zero_captcha.gemspec +25 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e8f70c4d1910b8d269b4f6ab284dac6b97c0ac7b
|
4
|
+
data.tar.gz: 515a4fcf417ad0b0f6dbf8463147d7aa2df71352
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 87822e89be4d7b0875be5f3ef09f8d44aa4751888ffce5bc65edbe69f794ef1cf4c2a24d9bb78d6275e6f934ad5c8612982ef5e6f77e1e4c8cf7b731d5f8c4f5
|
7
|
+
data.tar.gz: 8d2b43bb65f869c31ccb93d4f93a34c0cdb06f391fa9386022dfefcdc825aaffb872cfcd039d677e9112ebba9bc55e42a81e0247df506108da6e74c590ec3a48
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Infosimples
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
Developed by [Infosimples](https://infosimples.com), a brazilian company that
|
2
|
+
offers [data extraction solutions](https://infosimples.com/en/data-engineering)
|
3
|
+
and [Ruby on Rails development](https://infosimples.com/en/software-development).
|
4
|
+
|
5
|
+
|
6
|
+
# ZeroCaptcha
|
7
|
+
|
8
|
+
ZeroCaptcha is a Ruby API for an enterprise captcha solving service developed by
|
9
|
+
Infosimples that is 100% powered by artificial intelligence software.
|
10
|
+
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'zero_captcha', '~> 1.0.0'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install zero_captcha
|
27
|
+
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
1. **Create a client**
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
# Create a client
|
35
|
+
#
|
36
|
+
client = ZeroCaptcha.new('mytoken')
|
37
|
+
```
|
38
|
+
|
39
|
+
2. **Solve a captcha**
|
40
|
+
|
41
|
+
There are two methods available: **decode** and **decode!**
|
42
|
+
* **decode** doesn't raise exceptions.
|
43
|
+
* **decode!** may raise a *ZeroCaptcha::Error* if something goes wrong.
|
44
|
+
|
45
|
+
If the solution is not available, an empty captcha object will be returned.
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
captcha = client.decode(url: 'http://bit.ly/1xXZcKo', solver: 'captcha-type-1')
|
49
|
+
captcha.text # Solution of the captcha
|
50
|
+
captcha.id # Numeric ID of the captcha solved by ZeroCaptcha
|
51
|
+
captcha.correct? # true if the solution is correct
|
52
|
+
captcha.duration # How long it took to solve the captcha in milliseconds.
|
53
|
+
```
|
54
|
+
|
55
|
+
You can also specify *path*, *file*, *raw* and *raw64* when decoding an image.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
client.decode(path: 'path/to/my/captcha/file', solver: 'captcha-type-1')
|
59
|
+
|
60
|
+
client.decode(file: File.open('path/to/my/captcha/file', 'rb'), solver: 'captcha-type-1')
|
61
|
+
|
62
|
+
client.decode(raw: File.open('path/to/my/captcha/file', 'rb').read, solver: 'captcha-type-1')
|
63
|
+
|
64
|
+
client.decode(raw64: Base64.encode64(File.open('path/to/my/captcha/file', 'rb').read), solver: 'captcha-type-1')
|
65
|
+
```
|
66
|
+
|
67
|
+
> Internally, the gem will always convert the image to raw64 (binary base64 encoded).
|
68
|
+
|
69
|
+
3. **Report incorrectly solved captcha for refund**
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
captcha = client.report_incorrect(130920620) # with 130920620 as the captcha id
|
73
|
+
```
|
74
|
+
|
75
|
+
> ***Warning:*** *do not abuse on this method, otherwise you may get banned*
|
76
|
+
|
77
|
+
4. **Report correctly solved captcha for statistics**
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
captcha = client.report_correct(130920620) # with 130920620 as the captcha id
|
81
|
+
```
|
82
|
+
|
83
|
+
## Notes
|
84
|
+
|
85
|
+
#### Thread-safety
|
86
|
+
|
87
|
+
The API is thread-safe, which means it is perfectly fine to share a client
|
88
|
+
instance between multiple threads.
|
89
|
+
|
90
|
+
#### Ruby dependencies
|
91
|
+
|
92
|
+
ZeroCaptcha don't require specific dependencies. That saves you memory and
|
93
|
+
avoid conflicts with other gems.
|
94
|
+
|
95
|
+
#### Input image format
|
96
|
+
|
97
|
+
Any format you use in the decode method (url, file, path, raw, raw64) will
|
98
|
+
always be converted to a raw64, which is a binary base64 encoded string. So, if
|
99
|
+
you already have this format available on your side, there's no need to do
|
100
|
+
convertions before calling the API.
|
101
|
+
|
102
|
+
> Our recomendation is to never convert your image format, unless needed. Let
|
103
|
+
> the gem convert internally. It may save you resources (CPU, memory and IO).
|
104
|
+
|
105
|
+
#### Versioning
|
106
|
+
|
107
|
+
ZeroCaptcha gem uses [Semantic Versioning](http://semver.org/).
|
108
|
+
|
109
|
+
#### Ruby versions
|
110
|
+
|
111
|
+
This gem has been tested with the following versions of Ruby:
|
112
|
+
|
113
|
+
* MRI 2.2.2
|
114
|
+
* MRI 2.2.0
|
115
|
+
* MRI 2.1.5
|
116
|
+
* MRI 2.0.0
|
117
|
+
* MRI 1.9.3
|
118
|
+
|
119
|
+
# Maintainers
|
120
|
+
|
121
|
+
* [Rafael Barbolo](http://github.com/barbolo)
|
122
|
+
|
123
|
+
|
124
|
+
## Contributing
|
125
|
+
|
126
|
+
1. Fork it ( https://github.com/infosimples/zero_captcha/fork )
|
127
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
128
|
+
3. **Run/add tests (RSpec)**
|
129
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
130
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
131
|
+
6. Create a new Pull Request
|
132
|
+
7. Yay. Thanks for contributing :)
|
133
|
+
|
134
|
+
All contributors:
|
135
|
+
https://github.com/infosimples/zero_captcha/graphs/contributors
|
136
|
+
|
137
|
+
|
138
|
+
# License
|
139
|
+
|
140
|
+
MIT License. Copyright (C) 2011-2015 Infosimples. https://infosimples.com/
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "zero_captcha"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/lib/zero_captcha.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'json'
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
# The module ZeroCaptcha contains all the code for the zero_captcha gem.
|
6
|
+
# It acts as a safely namespace that isolates logic from ZeroCaptcha from any
|
7
|
+
# project that uses it.
|
8
|
+
#
|
9
|
+
module ZeroCaptcha
|
10
|
+
# Create a ZeroCaptcha API client. This is a shortcut to
|
11
|
+
# ZeroCaptcha::Client.new.
|
12
|
+
#
|
13
|
+
def self.new(*args)
|
14
|
+
ZeroCaptcha::Client.new(*args)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Base class of a model object returned by ZeroCaptcha API.
|
18
|
+
#
|
19
|
+
class Model
|
20
|
+
def initialize(values = {})
|
21
|
+
values.each do |key, value|
|
22
|
+
send("#{key}=", value) if respond_to?("#{key}=")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'zero_captcha/client'
|
29
|
+
require 'zero_captcha/errors'
|
30
|
+
require 'zero_captcha/http'
|
31
|
+
require 'zero_captcha/models/captcha'
|
32
|
+
require 'zero_captcha/version'
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module ZeroCaptcha
|
2
|
+
# ZeroCaptcha::Client is a client that communicates with the ZeroCaptcha API:
|
3
|
+
# https://zerocaptcha.infosimples.com/.
|
4
|
+
#
|
5
|
+
class Client
|
6
|
+
BASE_URL = 'https://zerocaptcha.infosimples.com/api/v1/captcha/:action.json'
|
7
|
+
|
8
|
+
attr_accessor :token, :timeout
|
9
|
+
|
10
|
+
# Create a ZeroCaptcha API client.
|
11
|
+
#
|
12
|
+
# @param [String] token Token of the ZeroCaptcha account.
|
13
|
+
# @param [Hash] options Options hash.
|
14
|
+
# @option options [Integer] :timeout (60) Seconds before giving up of a
|
15
|
+
# captcha being solved.
|
16
|
+
#
|
17
|
+
# @return [ZeroCaptcha::Client] A Client instance.
|
18
|
+
#
|
19
|
+
def initialize(token, options = {})
|
20
|
+
self.token = token
|
21
|
+
self.timeout = options[:timeout] || 60
|
22
|
+
end
|
23
|
+
|
24
|
+
# Decode the text from an image (i.e. solve a captcha).
|
25
|
+
#
|
26
|
+
# @param [Hash] options Options hash.
|
27
|
+
# @option options [String] :url URL of the image to be decoded.
|
28
|
+
# @option options [String] :path File path of the image to be decoded.
|
29
|
+
# @option options [File] :file File instance with image to be decoded.
|
30
|
+
# @option options [String] :raw Binary content of the image to be
|
31
|
+
# decoded.
|
32
|
+
# @option options [String] :raw64 Binary content encoded in base64 of the
|
33
|
+
# image to be decoded.
|
34
|
+
#
|
35
|
+
# @return [ZeroCaptcha::Captcha] The captcha (with solution) or an empty
|
36
|
+
# hash if something goes wrong.
|
37
|
+
#
|
38
|
+
def decode(options = {})
|
39
|
+
decode!(options)
|
40
|
+
rescue ZeroCaptcha::Error
|
41
|
+
ZeroCaptcha::Captcha.new
|
42
|
+
end
|
43
|
+
|
44
|
+
# Decode the text from an image (i.e. solve a captcha).
|
45
|
+
#
|
46
|
+
# @param [Hash] options Options hash.
|
47
|
+
# @option options [String] :url URL of the image to be decoded.
|
48
|
+
# @option options [String] :path File path of the image to be decoded.
|
49
|
+
# @option options [File] :file File instance with image to be decoded.
|
50
|
+
# @option options [String] :raw Binary content of the image to be
|
51
|
+
# decoded.
|
52
|
+
# @option options [String] :raw64 Binary content encoded in base64 of the
|
53
|
+
# image to be decoded.
|
54
|
+
#
|
55
|
+
# @return [ZeroCaptcha::Captcha] The captcha (with solution) if an error
|
56
|
+
# is not raised.
|
57
|
+
#
|
58
|
+
def decode!(options = {})
|
59
|
+
raw64 = load_captcha(options)
|
60
|
+
solver = options[:solver]
|
61
|
+
|
62
|
+
response = request(solver, :multipart, image64: raw64)
|
63
|
+
captcha = ZeroCaptcha::Captcha.new(response)
|
64
|
+
|
65
|
+
fail(ZeroCaptcha::IncorrectSolution) unless captcha.correct?
|
66
|
+
|
67
|
+
captcha
|
68
|
+
end
|
69
|
+
|
70
|
+
# Report incorrectly solved captcha for refund.
|
71
|
+
#
|
72
|
+
# @param [Integer] id Numeric ID of the captcha.
|
73
|
+
#
|
74
|
+
# @return [ZeroCaptcha::Captcha] The captcha with current "correct" value.
|
75
|
+
#
|
76
|
+
def report_incorrect(id)
|
77
|
+
response = request('report_incorrect', :post, id: id)
|
78
|
+
ZeroCaptcha::Captcha.new(response)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Report correctly solved captcha for statistics.
|
82
|
+
#
|
83
|
+
# @param [Integer] id Numeric ID of the captcha.
|
84
|
+
#
|
85
|
+
# @return [ZeroCaptcha::Captcha] The captcha with current "correct" value.
|
86
|
+
#
|
87
|
+
def report_correct(id)
|
88
|
+
response = request('report_correct', :post, id: id)
|
89
|
+
ZeroCaptcha::Captcha.new(response)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
# Load a captcha raw content encoded in base64 from options.
|
95
|
+
#
|
96
|
+
# @param [Hash] options Options hash.
|
97
|
+
# @option options [String] :url URL of the image to be decoded.
|
98
|
+
# @option options [String] :path File path of the image to be decoded.
|
99
|
+
# @option options [File] :file File instance with image to be decoded.
|
100
|
+
# @option options [String] :raw Binary content of the image to bedecoded.
|
101
|
+
# @option options [String] :raw64 Binary content encoded in base64 of the
|
102
|
+
# image to be decoded.
|
103
|
+
#
|
104
|
+
# @return [String] The binary image base64 encoded.
|
105
|
+
#
|
106
|
+
def load_captcha(options)
|
107
|
+
if options[:raw64]
|
108
|
+
options[:raw64]
|
109
|
+
elsif options[:raw]
|
110
|
+
Base64.encode64(options[:raw])
|
111
|
+
elsif options[:file]
|
112
|
+
Base64.encode64(options[:file].read)
|
113
|
+
elsif options[:path]
|
114
|
+
Base64.encode64(File.open(options[:path], 'rb').read)
|
115
|
+
elsif options[:url]
|
116
|
+
Base64.encode64(ZeroCaptcha::HTTP.open_url(options[:url]))
|
117
|
+
else
|
118
|
+
fail ZeroCaptcha::ArgumentError, 'Illegal image format'
|
119
|
+
end
|
120
|
+
rescue
|
121
|
+
raise ZeroCaptcha::InvalidCaptcha
|
122
|
+
end
|
123
|
+
|
124
|
+
# Perform an HTTP request to the ZeroCaptcha API.
|
125
|
+
#
|
126
|
+
# @param [String] action API method name.
|
127
|
+
# @param [Symbol] method HTTP method (:get, :post, :multipart).
|
128
|
+
# @param [Hash] payload Data to be sent through the HTTP request.
|
129
|
+
#
|
130
|
+
# @return [Hash] Response from the ZeroCaptcha API.
|
131
|
+
#
|
132
|
+
def request(action, method = :get, payload = {})
|
133
|
+
res = ZeroCaptcha::HTTP.request(
|
134
|
+
url: BASE_URL.gsub(':action', action),
|
135
|
+
timeout: timeout,
|
136
|
+
method: method,
|
137
|
+
payload: payload.merge(token: token)
|
138
|
+
)
|
139
|
+
JSON.parse(res)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ZeroCaptcha
|
2
|
+
# This is the base DeathByCaptcha exception class. Rescue it if you want to
|
3
|
+
# catch any exception that might be raised.
|
4
|
+
#
|
5
|
+
class Error < Exception
|
6
|
+
end
|
7
|
+
|
8
|
+
class ArgumentError < Error
|
9
|
+
end
|
10
|
+
|
11
|
+
class InvalidCaptcha < Error
|
12
|
+
def initialize
|
13
|
+
super('The captcha is empty or invalid')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class InvalidCaptchaType < Error
|
18
|
+
def initialize
|
19
|
+
super('Captcha type is invalid or cannot be solved by ZeroCaptcha')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Timeout < Error
|
24
|
+
def initialize
|
25
|
+
super('The captcha was not solved in the expected time')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class IncorrectSolution < Error
|
30
|
+
def initialize
|
31
|
+
super('The captcha could not be solved correctly')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class APIForbidden < Error
|
36
|
+
def initialize
|
37
|
+
super('Access denied, please check your credentials and/or balance')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class APIBadRequest < Error
|
42
|
+
def initialize
|
43
|
+
super('The Captcha was rejected, check if it\'s a valid image')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class APIResponseError < Error
|
48
|
+
def initialize(info)
|
49
|
+
super("Invalid API response: #{info}")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module ZeroCaptcha
|
2
|
+
# ZeroCaptcha::HTTP exposes common HTTP routines that can be used by the
|
3
|
+
# ZeroCaptcha API client.
|
4
|
+
#
|
5
|
+
class HTTP
|
6
|
+
# Retrieve the contents of a captcha URL supporting HTTPS and redirects.
|
7
|
+
#
|
8
|
+
# @param [String] url The captcha URL.
|
9
|
+
#
|
10
|
+
# @return [String] The contents of the captcha URL.
|
11
|
+
#
|
12
|
+
def self.open_url(url)
|
13
|
+
uri = URI(url)
|
14
|
+
|
15
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
16
|
+
|
17
|
+
if uri.scheme == 'https'
|
18
|
+
http.use_ssl = true
|
19
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
20
|
+
end
|
21
|
+
|
22
|
+
res = http.get(uri.request_uri)
|
23
|
+
|
24
|
+
if (redirect = res.header['location'])
|
25
|
+
open_url(redirect)
|
26
|
+
else
|
27
|
+
res.body
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Perform an HTTP request with support to multipart requests.
|
32
|
+
#
|
33
|
+
# @param [Hash] options Options hash.
|
34
|
+
# @param options [String] url URL to be requested.
|
35
|
+
# @param options [Symbol] method HTTP method (:get, :post, :multipart).
|
36
|
+
# @param options [Hash] payload Data to be sent through the HTTP request.
|
37
|
+
# @param options [Integer] timeout HTTP open/read timeout in seconds.
|
38
|
+
#
|
39
|
+
# @return [String] Response body of the HTTP request.
|
40
|
+
#
|
41
|
+
def self.request(options = {})
|
42
|
+
uri = URI(options[:url])
|
43
|
+
method = options[:method] || :get
|
44
|
+
payload = options[:payload] || {}
|
45
|
+
timeout = options[:timeout] || 60
|
46
|
+
headers = { 'User-Agent' => ZeroCaptcha::USER_AGENT }
|
47
|
+
|
48
|
+
case method
|
49
|
+
when :get
|
50
|
+
uri.query = URI.encode_www_form(payload)
|
51
|
+
req = Net::HTTP::Get.new(uri.request_uri, headers)
|
52
|
+
|
53
|
+
when :post
|
54
|
+
req = Net::HTTP::Post.new(uri.request_uri, headers)
|
55
|
+
req.set_form_data(payload)
|
56
|
+
|
57
|
+
when :multipart
|
58
|
+
req = Net::HTTP::Post.new(uri.request_uri, headers)
|
59
|
+
boundary, body = prepare_multipart_data(payload)
|
60
|
+
req.content_type = "multipart/form-data; boundary=#{boundary}"
|
61
|
+
req.body = body
|
62
|
+
|
63
|
+
else
|
64
|
+
fail ZeroCaptcha::ArgumentError, "Illegal HTTP method (#{method})"
|
65
|
+
end
|
66
|
+
|
67
|
+
http = Net::HTTP.new(uri.hostname, uri.port)
|
68
|
+
http.use_ssl = true if (uri.scheme == 'https')
|
69
|
+
http.open_timeout = timeout
|
70
|
+
http.read_timeout = timeout
|
71
|
+
res = http.request(req)
|
72
|
+
|
73
|
+
case res
|
74
|
+
when Net::HTTPSuccess
|
75
|
+
res.body
|
76
|
+
|
77
|
+
when Net::HTTPBadRequest
|
78
|
+
fail ZeroCaptcha::APIBadRequest
|
79
|
+
|
80
|
+
when Net::HTTPUnauthorized, Net::HTTPForbidden
|
81
|
+
fail ZeroCaptcha::APIForbidden
|
82
|
+
|
83
|
+
when Net::HTTPNotFound
|
84
|
+
fail ZeroCaptcha::InvalidCaptchaType
|
85
|
+
|
86
|
+
when Net::HTTPGatewayTimeOut
|
87
|
+
fail ZeroCaptcha::Timeout
|
88
|
+
|
89
|
+
else
|
90
|
+
fail ZeroCaptcha::APIResponseError, res.body
|
91
|
+
end
|
92
|
+
|
93
|
+
rescue Net::OpenTimeout, Net::ReadTimeout
|
94
|
+
raise ZeroCaptcha::Timeout
|
95
|
+
end
|
96
|
+
|
97
|
+
# Prepare the multipart data to be sent via a :multipart request.
|
98
|
+
#
|
99
|
+
# @param [Hash] payload Data to be prepared via a multipart post.
|
100
|
+
#
|
101
|
+
# @return [String, String] Boundary and body for the multipart post.
|
102
|
+
#
|
103
|
+
def self.prepare_multipart_data(payload)
|
104
|
+
boundary = 'infosimples' + rand(1_000_000).to_s # a random unique string
|
105
|
+
|
106
|
+
content = []
|
107
|
+
payload.each do |param, value|
|
108
|
+
content << '--' + boundary
|
109
|
+
content << "Content-Disposition: form-data; name=\"#{param}\""
|
110
|
+
content << ''
|
111
|
+
content << value
|
112
|
+
end
|
113
|
+
content << '--' + boundary + '--'
|
114
|
+
content << ''
|
115
|
+
|
116
|
+
[boundary, content.join("\r\n")]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ZeroCaptcha
|
2
|
+
# Model of a Captcha returned by ZeroCaptcha API.
|
3
|
+
#
|
4
|
+
class Captcha < ZeroCaptcha::Model
|
5
|
+
attr_accessor :id, :text, :code, :correct, :duration_in_milliseconds,
|
6
|
+
:created_at, :created_at_not_parsed
|
7
|
+
|
8
|
+
alias_method :correct?, :correct
|
9
|
+
alias_method :duration, :duration_in_milliseconds
|
10
|
+
|
11
|
+
def created_at=(datetime)
|
12
|
+
self.created_at_not_parsed = datetime
|
13
|
+
@created_at = Time.parse(datetime)
|
14
|
+
rescue
|
15
|
+
datetime
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'zero_captcha/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'zero_captcha'
|
8
|
+
spec.version = ZeroCaptcha::VERSION
|
9
|
+
spec.authors = ['Rafael Barbolo', 'Rafael Ivan Garcia']
|
10
|
+
spec.email = ["zerocaptcha@infosimples.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Ruby API for ZeroCaptcha (Captcha Solver as a Service for the Enterprise)}
|
13
|
+
spec.description = %q{ZeroCaptcha allows companies to solve captchas with artificial intelligence software, which is faster than humans and very accurate}
|
14
|
+
spec.homepage = "https://github.com/infosimples/zero_captcha"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.1"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zero_captcha
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rafael Barbolo
|
8
|
+
- Rafael Ivan Garcia
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-06-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.9'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.9'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '10.0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '10.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '3.1'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '3.1'
|
56
|
+
description: ZeroCaptcha allows companies to solve captchas with artificial intelligence
|
57
|
+
software, which is faster than humans and very accurate
|
58
|
+
email:
|
59
|
+
- zerocaptcha@infosimples.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- ".gitignore"
|
65
|
+
- ".rspec"
|
66
|
+
- CHANGELOG.md
|
67
|
+
- Gemfile
|
68
|
+
- LICENSE
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- bin/console
|
72
|
+
- bin/setup
|
73
|
+
- lib/zero_captcha.rb
|
74
|
+
- lib/zero_captcha/client.rb
|
75
|
+
- lib/zero_captcha/errors.rb
|
76
|
+
- lib/zero_captcha/http.rb
|
77
|
+
- lib/zero_captcha/models/captcha.rb
|
78
|
+
- lib/zero_captcha/version.rb
|
79
|
+
- zero_captcha.gemspec
|
80
|
+
homepage: https://github.com/infosimples/zero_captcha
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.4.8
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Ruby API for ZeroCaptcha (Captcha Solver as a Service for the Enterprise)
|
104
|
+
test_files: []
|