deathbycaptcha 5.0.2 → 5.2.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 +5 -5
- data/LICENSE.txt +1 -1
- data/README.md +146 -19
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/captchas/2.jpg +0 -0
- data/captchas/3-banner.jpg +0 -0
- data/captchas/3-grid.jpg +0 -0
- data/deathbycaptcha.gemspec +6 -2
- data/lib/deathbycaptcha.rb +1 -0
- data/lib/deathbycaptcha/client.rb +15 -8
- data/lib/deathbycaptcha/client/http.rb +23 -9
- data/lib/deathbycaptcha/client/socket.rb +7 -4
- data/lib/deathbycaptcha/models/captcha.rb +9 -0
- data/lib/deathbycaptcha/version.rb +1 -1
- data/spec/lib/image_captcha_spec.rb +80 -0
- metadata +14 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b7b0ae41ffa4cc961dc9600c23ec9f0e56bf09261fa4766ed2aa1cd686a2a09f
|
4
|
+
data.tar.gz: 87885c289fce41e9a34696514dc067b62b025a45e89f7728aaf28146beba4111
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 926bfd8b477e4d3888947bfca51521402c0f170c04fb70244b31fc9fa8aea47904f00587ea9f95fe9c9cb62c1c6780164aa59ef1bed19e0ac9e232adf01690a7
|
7
|
+
data.tar.gz: 72925f985964bf277675ebc86373871f0a3c865eb7996b0eb73bde1900d14d4d8e7b3765d1ced32979c0baae3bed7d762ca8d56de9273ed48e3d42e4452c5251
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
Developed by [Infosimples](https://infosimples.com), a brazilian company that
|
2
|
-
offers [data extraction solutions](https://infosimples.com/en/data-engineering)
|
3
|
-
|
2
|
+
offers [data extraction solutions](https://infosimples.com/en/data-engineering).
|
3
|
+
|
4
|
+
We suggest you to also check [2Captcha.com](http://2captcha.com/?from=1025109)
|
5
|
+
for a cheaper service. You can find it's gem fully compatible with the
|
6
|
+
deathbycaptcha gem at https://github.com/infosimples/two_captcha.
|
7
|
+
|
8
|
+
[Contact us](https://infosimples.com/en) if you need enterprise services for
|
9
|
+
CAPTCHAs solving or Internet automation.
|
4
10
|
|
5
11
|
|
6
12
|
# DeathByCaptcha
|
@@ -24,14 +30,12 @@ Or install it yourself as:
|
|
24
30
|
|
25
31
|
$ gem install deathbycaptcha
|
26
32
|
|
27
|
-
|
28
33
|
## Usage
|
29
34
|
|
30
35
|
1. **Create a client**
|
31
36
|
|
32
37
|
```ruby
|
33
38
|
# Create a client (:socket and :http clients are available)
|
34
|
-
#
|
35
39
|
client = DeathByCaptcha.new('myusername', 'mypassword', :http)
|
36
40
|
```
|
37
41
|
|
@@ -44,7 +48,7 @@ Or install it yourself as:
|
|
44
48
|
If the solution is not available, an empty captcha object will be returned.
|
45
49
|
|
46
50
|
```ruby
|
47
|
-
captcha = client.decode(url: 'http://bit.ly/1xXZcKo')
|
51
|
+
captcha = client.decode!(url: 'http://bit.ly/1xXZcKo')
|
48
52
|
captcha.text # Solution of the captcha
|
49
53
|
captcha.id # Numeric ID of the captcha solved by DeathByCaptcha
|
50
54
|
captcha.is_correct # true if the solution is correct
|
@@ -53,16 +57,17 @@ Or install it yourself as:
|
|
53
57
|
You can also specify *path*, *file*, *raw* and *raw64* when decoding an image.
|
54
58
|
|
55
59
|
```ruby
|
56
|
-
client.decode(path: 'path/to/my/captcha/file')
|
60
|
+
client.decode!(path: 'path/to/my/captcha/file')
|
57
61
|
|
58
|
-
client.decode(file: File.open('path/to/my/captcha/file', 'rb'))
|
62
|
+
client.decode!(file: File.open('path/to/my/captcha/file', 'rb'))
|
59
63
|
|
60
|
-
client.decode(raw: File.open('path/to/my/captcha/file', 'rb').read)
|
64
|
+
client.decode!(raw: File.open('path/to/my/captcha/file', 'rb').read)
|
61
65
|
|
62
|
-
client.decode(raw64: Base64.encode64(File.open('path/to/my/captcha/file', 'rb').read))
|
66
|
+
client.decode!(raw64: Base64.encode64(File.open('path/to/my/captcha/file', 'rb').read))
|
63
67
|
```
|
64
68
|
|
65
|
-
> Internally, the gem will always convert
|
69
|
+
> Internally, the gem will always convert any image to raw64 (binary base64
|
70
|
+
encoded).
|
66
71
|
|
67
72
|
3. **Retrieve a previously solved captcha**
|
68
73
|
|
@@ -97,6 +102,135 @@ Or install it yourself as:
|
|
97
102
|
status.is_service_overloaded # true if DeathByCaptcha is overloaded/unresponsive
|
98
103
|
```
|
99
104
|
|
105
|
+
## New reCAPTCHA
|
106
|
+
|
107
|
+
> It's currently available only with the :http client.
|
108
|
+
|
109
|
+
To solve captchas similar to
|
110
|
+
[reCAPTCHA v2](https://support.google.com/recaptcha/?hl=en#6262736), you can use
|
111
|
+
both the DeathByCaptcha's **Coordinates API** or **Image Group API**.
|
112
|
+
|
113
|
+
Please, read the oficial documentation at
|
114
|
+
http://www.deathbycaptcha.com/user/api/newrecaptcha.
|
115
|
+
|
116
|
+
### Using the Coordinates API
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
# Read above all the instructions on how to solve a captcha.
|
120
|
+
captcha = client.decode!(type: 2, url: 'http://bit.ly/1VCUuzk')
|
121
|
+
```
|
122
|
+
|
123
|
+
You should specify arguments with *type = 2* and an image similar to a screenshot of
|
124
|
+
the captcha. See an example:
|
125
|
+
|
126
|
+
**Captcha (screenshot)**
|
127
|
+
|
128
|
+
> the argument is passed as *url*, *path*, *file*, *raw* or *raw64*
|
129
|
+
|
130
|
+

|
131
|
+
|
132
|
+
The response will be an array containing coordinates (x, y) where the human
|
133
|
+
clicked to solve the captcha. For the captcha above it should look something
|
134
|
+
like:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
# captcha.text
|
138
|
+
"[[30,143],[241,325]]"
|
139
|
+
|
140
|
+
# captcha.coordinates
|
141
|
+
[[30, 143], [241, 325]]
|
142
|
+
```
|
143
|
+
|
144
|
+
### Using the Image Group API
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
# Read above all the instructions on how to solve a captcha.
|
148
|
+
captcha = client.decode!(
|
149
|
+
type: 3,
|
150
|
+
url: 'http://bit.ly/1i1CIaB', # single image with the clickable grid
|
151
|
+
banner: { url: 'http://bit.ly/1JTG4T3' }, # the banner image
|
152
|
+
banner_text: 'Click all images with bananas' # the banner text
|
153
|
+
)
|
154
|
+
```
|
155
|
+
|
156
|
+
You should specify arguments with *type = 3* and the decomposed captcha as seen in the
|
157
|
+
example below:
|
158
|
+
|
159
|
+
**Captcha: images grid**
|
160
|
+
|
161
|
+
> the argument is passed as *url*, *path*, *file*, *raw* or *raw64*
|
162
|
+
|
163
|
+

|
164
|
+
|
165
|
+
**Captcha: banner**
|
166
|
+
|
167
|
+

|
168
|
+
|
169
|
+
**Captcha: banner text**
|
170
|
+
|
171
|
+
> Click all images with bananas
|
172
|
+
|
173
|
+
The response will be an array containing the indexes for each image that should
|
174
|
+
be clicked counting from left to right. For the captcha above it should look
|
175
|
+
something like:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
# captcha.text
|
179
|
+
"[1,9]"
|
180
|
+
|
181
|
+
# captcha.indexes
|
182
|
+
[1, 9]
|
183
|
+
```
|
184
|
+
|
185
|
+
## New Recaptcha by Token API
|
186
|
+
|
187
|
+
> It's currently available only with the :http client.
|
188
|
+
|
189
|
+
To solve captchas similar to
|
190
|
+
[reCAPTCHA v2](https://support.google.com/recaptcha/?hl=en#6262736), you can also use
|
191
|
+
**Token API**
|
192
|
+
|
193
|
+
Please, read the oficial documentation at
|
194
|
+
http://deathbycaptcha.com/user/api/newtokenrecaptcha
|
195
|
+
|
196
|
+
### Using the Token API
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
# Read above all the instructions on how to solve a captcha.
|
200
|
+
captcha = client.decode!(type: 4, token_params: {
|
201
|
+
# optional proxy if needed and server verifies
|
202
|
+
#proxy: "http://127.0.0.1:3128",
|
203
|
+
#proxytype: "HTTP",
|
204
|
+
googlekey: "6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5",
|
205
|
+
pageurl: "https://patrickhlauke.github.io/recaptcha/"
|
206
|
+
})
|
207
|
+
```
|
208
|
+
|
209
|
+
You should specify arguments with *type = 4* and an all token params required by DBC API
|
210
|
+
|
211
|
+
The response will be a text (token), which you can access with **text** or **token** method.
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
# captcha.text
|
215
|
+
"03AOPBWq_RPO2vLzyk0h8gH0cA2X4v3tpYCPZR6Y4yxKy1s3Eo7CHZRQntxrd
|
216
|
+
saD2H0e6S3547xi1FlqJB4rob46J0-wfZMj6YpyVa0WGCfpWzBWcLn7tO_EYs
|
217
|
+
vEC_3kfLNINWa5LnKrnJTDXTOz-JuCKvEXx0EQqzb0OU4z2np4uyu79lc_Ndv
|
218
|
+
L0IRFc3Cslu6UFV04CIfqXJBWCE5MY0Ag918r14b43ZdpwHSaVVrUqzCQMCyb
|
219
|
+
cGq0yxLQf9eSexFiAWmcWLI5nVNA81meTXhQlyCn5bbbI2IMSEErDqceZjf1m
|
220
|
+
X3M67BhIb4"
|
221
|
+
|
222
|
+
# captcha.token
|
223
|
+
"03AOPBWq_RPO2vLzyk0h8gH0cA2X4v3tpYCPZR6Y4yxKy1s3Eo7CHZRQntxrd
|
224
|
+
saD2H0e6S3547xi1FlqJB4rob46J0-wfZMj6YpyVa0WGCfpWzBWcLn7tO_EYs
|
225
|
+
vEC_3kfLNINWa5LnKrnJTDXTOz-JuCKvEXx0EQqzb0OU4z2np4uyu79lc_Ndv
|
226
|
+
L0IRFc3Cslu6UFV04CIfqXJBWCE5MY0Ag918r14b43ZdpwHSaVVrUqzCQMCyb
|
227
|
+
cGq0yxLQf9eSexFiAWmcWLI5nVNA81meTXhQlyCn5bbbI2IMSEErDqceZjf1m
|
228
|
+
X3M67BhIb4"
|
229
|
+
```
|
230
|
+
|
231
|
+
> Those captchas sometimes took more than 60 seconds to solve
|
232
|
+
> So consider increasing the client's *timeout*
|
233
|
+
|
100
234
|
## Notes
|
101
235
|
|
102
236
|
#### Thread-safety
|
@@ -121,7 +255,7 @@ firewall.
|
|
121
255
|
#### Ruby dependencies
|
122
256
|
|
123
257
|
DeathByCaptcha >= 5.0.0 don't require specific dependencies. That saves you
|
124
|
-
|
258
|
+
memory and avoid conflicts with other gems.
|
125
259
|
|
126
260
|
#### Input image format
|
127
261
|
|
@@ -131,7 +265,7 @@ you already have this format available on your side, there's no need to do
|
|
131
265
|
convertions before calling the API.
|
132
266
|
|
133
267
|
> Our recomendation is to never convert your image format, unless needed. Let
|
134
|
-
> the gem convert internally. It may save you resources (CPU,
|
268
|
+
> the gem convert internally. It may save you resources (CPU, memory and IO).
|
135
269
|
|
136
270
|
#### Versioning
|
137
271
|
|
@@ -153,13 +287,6 @@ This gem has been tested on the following versions of Ruby:
|
|
153
287
|
* MRI 2.0.0
|
154
288
|
* MRI 1.9.3
|
155
289
|
|
156
|
-
# Maintainers
|
157
|
-
|
158
|
-
* [Débora Setton Fernandes](http://github.com/deborasetton)
|
159
|
-
* [Rafael Barbolo](http://github.com/barbolo)
|
160
|
-
* [Rafael Ivan Garcia](http://github.com/rafaelivan)
|
161
|
-
|
162
|
-
|
163
290
|
## Contributing
|
164
291
|
|
165
292
|
1. Fork it ( https://github.com/infosimples/deathbycaptcha/fork )
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "deathbycaptcha"
|
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/captchas/2.jpg
ADDED
Binary file
|
Binary file
|
data/captchas/3-grid.jpg
ADDED
Binary file
|
data/deathbycaptcha.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'deathbycaptcha/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "deathbycaptcha"
|
8
8
|
spec.version = DeathByCaptcha::VERSION
|
9
|
-
spec.authors = ["
|
9
|
+
spec.authors = ["Rafael Barbolo, Rafael Ivan Garcia"]
|
10
10
|
spec.email = ["team@infosimples.com.br"]
|
11
11
|
spec.summary = %q{Ruby API for DeathByCaptcha (Captcha Solver as a Service)}
|
12
12
|
spec.description = %q{DeathByCaptcha allows you to solve captchas with manual labor}
|
@@ -14,7 +14,11 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
17
|
-
|
17
|
+
|
18
|
+
# Since our currently binstubs are used only during the gem's development, we
|
19
|
+
# are ignoring them in the gem specification.
|
20
|
+
# spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
|
18
22
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
23
|
spec.require_paths = ["lib"]
|
20
24
|
|
data/lib/deathbycaptcha.rb
CHANGED
@@ -12,7 +12,7 @@ module DeathByCaptcha
|
|
12
12
|
#
|
13
13
|
class Client
|
14
14
|
|
15
|
-
attr_accessor :username, :password, :timeout, :polling
|
15
|
+
attr_accessor :username, :password, :timeout, :polling, :hostname
|
16
16
|
|
17
17
|
# Create a DeathByCaptcha API client
|
18
18
|
#
|
@@ -43,6 +43,7 @@ module DeathByCaptcha
|
|
43
43
|
# @param [Hash] options Options hash.
|
44
44
|
# @option options [Integer] :timeout (60) Seconds before giving up.
|
45
45
|
# @option options [Integer] :polling (5) Seconds for polling the solution.
|
46
|
+
# @option options [String] :hostname ('api.dbcapi.me') Custom API hostname.
|
46
47
|
#
|
47
48
|
# @return [DeathByCaptcha::Client] A Client instance.
|
48
49
|
#
|
@@ -51,6 +52,7 @@ module DeathByCaptcha
|
|
51
52
|
self.password = password
|
52
53
|
self.timeout = options[:timeout] || 60
|
53
54
|
self.polling = options[:polling] || 5
|
55
|
+
self.hostname = options[:hostname] || 'api.dbcapi.me'
|
54
56
|
end
|
55
57
|
|
56
58
|
# Decode the text from an image (i.e. solve a captcha).
|
@@ -84,19 +86,24 @@ module DeathByCaptcha
|
|
84
86
|
def decode!(options = {})
|
85
87
|
started_at = Time.now
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
+
# don't load image data for Token API v2 & v3
|
90
|
+
raw64 = nil
|
91
|
+
unless [4, 5].include? options[:type]
|
92
|
+
raw64 = load_captcha(options)
|
93
|
+
raise DeathByCaptcha::InvalidCaptcha if raw64.to_s.empty?
|
94
|
+
end
|
95
|
+
|
96
|
+
decoded_captcha = self.upload(options.merge(raw64: raw64))
|
89
97
|
|
90
|
-
|
91
|
-
while _captcha.text.to_s.empty?
|
98
|
+
while decoded_captcha.text.to_s.empty?
|
92
99
|
sleep(self.polling)
|
93
|
-
|
100
|
+
decoded_captcha = self.captcha(decoded_captcha.id)
|
94
101
|
raise DeathByCaptcha::Timeout if (Time.now - started_at) > self.timeout
|
95
102
|
end
|
96
103
|
|
97
|
-
raise DeathByCaptcha::IncorrectSolution if !
|
104
|
+
raise DeathByCaptcha::IncorrectSolution if !decoded_captcha.is_correct
|
98
105
|
|
99
|
-
|
106
|
+
decoded_captcha
|
100
107
|
end
|
101
108
|
|
102
109
|
# Retrieve information from an uploaded captcha.
|
@@ -3,9 +3,6 @@ module DeathByCaptcha
|
|
3
3
|
# HTTP client for DeathByCaptcha API.
|
4
4
|
#
|
5
5
|
class Client::HTTP < Client
|
6
|
-
|
7
|
-
BASE_URL = 'http://api.dbcapi.me/api'
|
8
|
-
|
9
6
|
# Retrieve information from an uploaded captcha.
|
10
7
|
#
|
11
8
|
# @param [Integer] captcha_id Numeric ID of the captcha.
|
@@ -53,8 +50,26 @@ module DeathByCaptcha
|
|
53
50
|
#
|
54
51
|
# @return [DeathByCaptcha::Captcha] The captcha object (not solved yet).
|
55
52
|
#
|
56
|
-
def upload(
|
57
|
-
|
53
|
+
def upload(options = {})
|
54
|
+
payload = {}
|
55
|
+
payload[:captchafile] = "base64:#{options[:raw64]}"
|
56
|
+
payload[:type] = options[:type] if options[:type].to_i > 0
|
57
|
+
|
58
|
+
if options[:type].to_i == 3
|
59
|
+
banner64 = load_captcha(options[:banner])
|
60
|
+
raise DeathByCaptcha::InvalidCaptcha if banner64.to_s.empty?
|
61
|
+
|
62
|
+
payload[:banner] = "base64:#{banner64}"
|
63
|
+
payload[:banner_text] = options[:banner_text].to_s
|
64
|
+
|
65
|
+
elsif [4, 5].include? options[:type].to_i
|
66
|
+
payload = {
|
67
|
+
type: options[:type].to_i,
|
68
|
+
token_params: options[:token_params].to_json,
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
response = perform('captcha', :post_multipart, payload)
|
58
73
|
DeathByCaptcha::Captcha.new(response)
|
59
74
|
end
|
60
75
|
|
@@ -74,19 +89,18 @@ module DeathByCaptcha
|
|
74
89
|
headers = { 'User-Agent' => DeathByCaptcha::API_VERSION }
|
75
90
|
|
76
91
|
if method == :post
|
77
|
-
uri = URI("
|
92
|
+
uri = URI("http://#{self.hostname}/api/#{action}")
|
78
93
|
req = Net::HTTP::Post.new(uri.request_uri, headers)
|
79
94
|
req.set_form_data(payload)
|
80
95
|
|
81
96
|
elsif method == :post_multipart
|
82
|
-
uri = URI("
|
97
|
+
uri = URI("http://#{self.hostname}/api/#{action}")
|
83
98
|
req = Net::HTTP::Post.new(uri.request_uri, headers)
|
84
99
|
boundary, body = prepare_multipart_data(payload)
|
85
100
|
req.content_type = "multipart/form-data; boundary=#{boundary}"
|
86
101
|
req.body = body
|
87
|
-
|
88
102
|
else
|
89
|
-
uri = URI("
|
103
|
+
uri = URI("http://#{self.hostname}/api/#{action}?#{URI.encode_www_form(payload)}")
|
90
104
|
req = Net::HTTP::Get.new(uri.request_uri, headers)
|
91
105
|
end
|
92
106
|
|
@@ -4,7 +4,6 @@ module DeathByCaptcha
|
|
4
4
|
#
|
5
5
|
class Client::Socket < Client
|
6
6
|
|
7
|
-
HOST = 'api.dbcapi.me'
|
8
7
|
PORTS = (8123..8130).to_a
|
9
8
|
|
10
9
|
# Retrieve information from an uploaded captcha.
|
@@ -54,8 +53,12 @@ module DeathByCaptcha
|
|
54
53
|
#
|
55
54
|
# @return [DeathByCaptcha::Captcha] The captcha object (not solved yet).
|
56
55
|
#
|
57
|
-
def upload(
|
58
|
-
|
56
|
+
def upload(options = {})
|
57
|
+
if options[:type] && options[:type].to_i != 1
|
58
|
+
# Socket client implementation currently supports only text captchas.
|
59
|
+
raise DeathByCaptcha::InvalidCaptcha
|
60
|
+
end
|
61
|
+
response = perform('upload', captcha: options[:raw64])
|
59
62
|
DeathByCaptcha::Captcha.new(response)
|
60
63
|
end
|
61
64
|
|
@@ -112,7 +115,7 @@ module DeathByCaptcha
|
|
112
115
|
#
|
113
116
|
def create_socket
|
114
117
|
socket = ::Socket.new(::Socket::AF_INET, ::Socket::SOCK_STREAM, 0)
|
115
|
-
sockaddr = ::Socket.sockaddr_in(PORTS.sample,
|
118
|
+
sockaddr = ::Socket.sockaddr_in(PORTS.sample, self.hostname)
|
116
119
|
begin # emulate blocking connect
|
117
120
|
socket.connect_nonblock(sockaddr)
|
118
121
|
rescue IO::WaitWritable
|
@@ -16,5 +16,14 @@ module DeathByCaptcha
|
|
16
16
|
def captcha=(value)
|
17
17
|
@captcha = value.to_i
|
18
18
|
end
|
19
|
+
|
20
|
+
def parsed_text
|
21
|
+
JSON.parse(text)
|
22
|
+
rescue
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
alias_method :coordinates, :parsed_text
|
26
|
+
alias_method :indexes, :parsed_text
|
27
|
+
alias_method :token, :text
|
19
28
|
end
|
20
29
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
username = CREDENTIALS['username']
|
4
|
+
password = CREDENTIALS['password']
|
5
|
+
path2 = './captchas/2.jpg' # path of the captcha (Coordinates API)
|
6
|
+
path3_grid = './captchas/3-grid.jpg' # path of the grid (Image Group API)
|
7
|
+
path3_banner = './captchas/3-banner.jpg' # path of the grid (Image Group API)
|
8
|
+
banner_text3 = 'Click all images with bananas'
|
9
|
+
token_params = {
|
10
|
+
#proxy: "http://127.0.0.1:3128",
|
11
|
+
#proxytype: "HTTP",
|
12
|
+
googlekey: "6Ld2sf4SAAAAAKSgzs0Q13IZhY02Pyo31S2jgOB5",
|
13
|
+
pageurl: "https://patrickhlauke.github.io/recaptcha/"
|
14
|
+
}
|
15
|
+
|
16
|
+
describe 'Solving an image based captcha' do
|
17
|
+
before(:all) { @client = DeathByCaptcha.new(username, password, :http) }
|
18
|
+
|
19
|
+
context 'Coordinates API' do
|
20
|
+
describe '#decode!' do
|
21
|
+
before(:all) { @captcha = @client.decode!(type: 2, path: path2) }
|
22
|
+
it { expect(@captcha).to be_a(DeathByCaptcha::Captcha) }
|
23
|
+
it { expect(@captcha.text).to match(/\A\[\[.*\]\]\Z/) }
|
24
|
+
it { expect(@captcha.coordinates).to be_a(Array) }
|
25
|
+
it { expect(@captcha.coordinates.size).to be > 0 }
|
26
|
+
it 'expect coordinates to be valid' do
|
27
|
+
@captcha.coordinates.each do |coordinate|
|
28
|
+
expect(coordinate).to be_a(Array)
|
29
|
+
expect(coordinate.size).to eq(2)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
it { expect(@captcha.is_correct).to be true }
|
33
|
+
it { expect(@captcha.id).to be > 0 }
|
34
|
+
it { expect(@captcha.id).to eq(@captcha.captcha) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'Image Group API' do
|
39
|
+
describe '#decode!' do
|
40
|
+
before(:all) do
|
41
|
+
@captcha = @client.decode!(
|
42
|
+
type: 3,
|
43
|
+
path: path3_grid,
|
44
|
+
banner: { path: path3_banner },
|
45
|
+
banner_text: banner_text3
|
46
|
+
)
|
47
|
+
end
|
48
|
+
it { expect(@captcha).to be_a(DeathByCaptcha::Captcha) }
|
49
|
+
it { expect(@captcha.text).to match(/\A\[.*\]\Z/) }
|
50
|
+
it { expect(@captcha.indexes).to be_a(Array) }
|
51
|
+
it { expect(@captcha.indexes.size).to be > 0 }
|
52
|
+
it 'expect indexes to be valid' do
|
53
|
+
@captcha.indexes.each do |index|
|
54
|
+
expect(index).to be_a(Numeric)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
it { expect(@captcha.is_correct).to be true }
|
58
|
+
it { expect(@captcha.id).to be > 0 }
|
59
|
+
it { expect(@captcha.id).to eq(@captcha.captcha) }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'Token API' do
|
64
|
+
describe '#decode!' do
|
65
|
+
before(:all) do
|
66
|
+
@captcha = @client.decode!(
|
67
|
+
type: 4,
|
68
|
+
token_params: token_params,
|
69
|
+
)
|
70
|
+
end
|
71
|
+
it { expect(@captcha).to be_a(DeathByCaptcha::Captcha) }
|
72
|
+
it { expect(@captcha.text).to eq(@captcha.token) }
|
73
|
+
it { expect(@captcha.token).to match(/\A"?\S+"?\Z/) }
|
74
|
+
it { expect(@captcha.token.size).to be > 30 }
|
75
|
+
it { expect(@captcha.is_correct).to be true }
|
76
|
+
it { expect(@captcha.id).to be > 0 }
|
77
|
+
it { expect(@captcha.id).to eq(@captcha.captcha) }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deathbycaptcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0
|
4
|
+
version: 5.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
autorequire:
|
7
|
+
- Rafael Barbolo, Rafael Ivan Garcia
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -65,7 +65,12 @@ files:
|
|
65
65
|
- LICENSE.txt
|
66
66
|
- README.md
|
67
67
|
- Rakefile
|
68
|
+
- bin/console
|
69
|
+
- bin/setup
|
68
70
|
- captchas/1.png
|
71
|
+
- captchas/2.jpg
|
72
|
+
- captchas/3-banner.jpg
|
73
|
+
- captchas/3-grid.jpg
|
69
74
|
- deathbycaptcha.gemspec
|
70
75
|
- lib/deathbycaptcha.rb
|
71
76
|
- lib/deathbycaptcha/client.rb
|
@@ -80,12 +85,13 @@ files:
|
|
80
85
|
- lib/deathbycaptcha/version.rb
|
81
86
|
- spec/credentials.yml.example
|
82
87
|
- spec/lib/client_spec.rb
|
88
|
+
- spec/lib/image_captcha_spec.rb
|
83
89
|
- spec/spec_helper.rb
|
84
90
|
homepage: https://github.com/infosimples/deathbycaptcha
|
85
91
|
licenses:
|
86
92
|
- MIT
|
87
93
|
metadata: {}
|
88
|
-
post_install_message:
|
94
|
+
post_install_message:
|
89
95
|
rdoc_options: []
|
90
96
|
require_paths:
|
91
97
|
- lib
|
@@ -100,12 +106,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
106
|
- !ruby/object:Gem::Version
|
101
107
|
version: '0'
|
102
108
|
requirements: []
|
103
|
-
|
104
|
-
|
105
|
-
signing_key:
|
109
|
+
rubygems_version: 3.1.4
|
110
|
+
signing_key:
|
106
111
|
specification_version: 4
|
107
112
|
summary: Ruby API for DeathByCaptcha (Captcha Solver as a Service)
|
108
113
|
test_files:
|
109
114
|
- spec/credentials.yml.example
|
110
115
|
- spec/lib/client_spec.rb
|
116
|
+
- spec/lib/image_captcha_spec.rb
|
111
117
|
- spec/spec_helper.rb
|