deathbycaptcha 5.0.2 → 5.0.3
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 +4 -4
- data/README.md +90 -10
- 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/lib/deathbycaptcha/client.rb +6 -5
- data/lib/deathbycaptcha/client/http.rb +14 -3
- data/lib/deathbycaptcha/client/socket.rb +6 -2
- data/lib/deathbycaptcha/models/captcha.rb +8 -0
- data/lib/deathbycaptcha/version.rb +1 -1
- data/spec/lib/image_captcha_spec.rb +56 -0
- metadata +12 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98c633b9bb114866ddf802c7420e8c44d737dffd
|
4
|
+
data.tar.gz: f940fb9797a688edebe3b90da31dbff445c1a27a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8dcf6fe8b34118de125bb698ffeabab7297631cdd7e740a63269e408c76555068a91232814e4e6417b4a83a4fb7db5be911e8273cf2f2f07455be5bab0e74683
|
7
|
+
data.tar.gz: 8fe87517c20ad3bd5bb1a3181c81d2fb2ba02658b4eeadad6e600d2b872ac1136eba1737a163f5bd306f8ebf072f14611e249390a02bbcf3feaa7be22a7dc3de
|
data/README.md
CHANGED
@@ -24,14 +24,12 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
$ gem install deathbycaptcha
|
26
26
|
|
27
|
-
|
28
27
|
## Usage
|
29
28
|
|
30
29
|
1. **Create a client**
|
31
30
|
|
32
31
|
```ruby
|
33
32
|
# Create a client (:socket and :http clients are available)
|
34
|
-
#
|
35
33
|
client = DeathByCaptcha.new('myusername', 'mypassword', :http)
|
36
34
|
```
|
37
35
|
|
@@ -44,7 +42,7 @@ Or install it yourself as:
|
|
44
42
|
If the solution is not available, an empty captcha object will be returned.
|
45
43
|
|
46
44
|
```ruby
|
47
|
-
captcha = client.decode(url: 'http://bit.ly/1xXZcKo')
|
45
|
+
captcha = client.decode!(url: 'http://bit.ly/1xXZcKo')
|
48
46
|
captcha.text # Solution of the captcha
|
49
47
|
captcha.id # Numeric ID of the captcha solved by DeathByCaptcha
|
50
48
|
captcha.is_correct # true if the solution is correct
|
@@ -53,16 +51,17 @@ Or install it yourself as:
|
|
53
51
|
You can also specify *path*, *file*, *raw* and *raw64* when decoding an image.
|
54
52
|
|
55
53
|
```ruby
|
56
|
-
client.decode(path: 'path/to/my/captcha/file')
|
54
|
+
client.decode!(path: 'path/to/my/captcha/file')
|
57
55
|
|
58
|
-
client.decode(file: File.open('path/to/my/captcha/file', 'rb'))
|
56
|
+
client.decode!(file: File.open('path/to/my/captcha/file', 'rb'))
|
59
57
|
|
60
|
-
client.decode(raw: File.open('path/to/my/captcha/file', 'rb').read)
|
58
|
+
client.decode!(raw: File.open('path/to/my/captcha/file', 'rb').read)
|
61
59
|
|
62
|
-
client.decode(raw64: Base64.encode64(File.open('path/to/my/captcha/file', 'rb').read))
|
60
|
+
client.decode!(raw64: Base64.encode64(File.open('path/to/my/captcha/file', 'rb').read))
|
63
61
|
```
|
64
62
|
|
65
|
-
> Internally, the gem will always convert
|
63
|
+
> Internally, the gem will always convert any image to raw64 (binary base64
|
64
|
+
encoded).
|
66
65
|
|
67
66
|
3. **Retrieve a previously solved captcha**
|
68
67
|
|
@@ -97,6 +96,86 @@ Or install it yourself as:
|
|
97
96
|
status.is_service_overloaded # true if DeathByCaptcha is overloaded/unresponsive
|
98
97
|
```
|
99
98
|
|
99
|
+
## New reCAPTCHA
|
100
|
+
|
101
|
+
> It's currently available only with the :http client.
|
102
|
+
|
103
|
+
To solve captchas similar to
|
104
|
+
[reCAPTCHA v2](https://support.google.com/recaptcha/?hl=en#6262736), you can use
|
105
|
+
both the DeathByCaptcha's **Coordinates API** or **Image Group API**.
|
106
|
+
|
107
|
+
Please, read the oficial documentation at
|
108
|
+
http://www.deathbycaptcha.com/user/api/newrecaptcha.
|
109
|
+
|
110
|
+
### Using the Coordinates API
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
# Read above all the instructions on how to solve a captcha.
|
114
|
+
captcha = client.decode!(type: 2, url: 'http://bit.ly/1VCUuzk')
|
115
|
+
```
|
116
|
+
|
117
|
+
You should specify arguments with *type = 2* and an image similar to a screenshot of
|
118
|
+
the captcha. See an example:
|
119
|
+
|
120
|
+
**Captcha (screenshot)**
|
121
|
+
|
122
|
+
> the argument is passed as *url*, *path*, *file*, *raw* or *raw64*
|
123
|
+
|
124
|
+

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

|
158
|
+
|
159
|
+
**Captcha: banner**
|
160
|
+
|
161
|
+

|
162
|
+
|
163
|
+
**Captcha: banner text**
|
164
|
+
|
165
|
+
> Click all images with bananas
|
166
|
+
|
167
|
+
The response will be an array containing the indexes for each image that should
|
168
|
+
be clicked counting from left to right. For the captcha above it should look
|
169
|
+
something like:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
# captcha.text
|
173
|
+
"[1,9]"
|
174
|
+
|
175
|
+
# captcha.indexes
|
176
|
+
[1, 9]
|
177
|
+
```
|
178
|
+
|
100
179
|
## Notes
|
101
180
|
|
102
181
|
#### Thread-safety
|
@@ -121,7 +200,7 @@ firewall.
|
|
121
200
|
#### Ruby dependencies
|
122
201
|
|
123
202
|
DeathByCaptcha >= 5.0.0 don't require specific dependencies. That saves you
|
124
|
-
|
203
|
+
memory and avoid conflicts with other gems.
|
125
204
|
|
126
205
|
#### Input image format
|
127
206
|
|
@@ -131,7 +210,7 @@ you already have this format available on your side, there's no need to do
|
|
131
210
|
convertions before calling the API.
|
132
211
|
|
133
212
|
> Our recomendation is to never convert your image format, unless needed. Let
|
134
|
-
> the gem convert internally. It may save you resources (CPU,
|
213
|
+
> the gem convert internally. It may save you resources (CPU, memory and IO).
|
135
214
|
|
136
215
|
#### Versioning
|
137
216
|
|
@@ -156,6 +235,7 @@ This gem has been tested on the following versions of Ruby:
|
|
156
235
|
# Maintainers
|
157
236
|
|
158
237
|
* [Débora Setton Fernandes](http://github.com/deborasetton)
|
238
|
+
* [Marcelo Mita](http://github.com/marcelomita)
|
159
239
|
* [Rafael Barbolo](http://github.com/barbolo)
|
160
240
|
* [Rafael Ivan Garcia](http://github.com/rafaelivan)
|
161
241
|
|
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
|
@@ -87,16 +87,17 @@ module DeathByCaptcha
|
|
87
87
|
raw64 = load_captcha(options)
|
88
88
|
raise DeathByCaptcha::InvalidCaptcha if raw64.to_s.empty?
|
89
89
|
|
90
|
-
|
91
|
-
|
90
|
+
decoded_captcha = self.upload(options.merge(raw64: raw64))
|
91
|
+
|
92
|
+
while decoded_captcha.text.to_s.empty?
|
92
93
|
sleep(self.polling)
|
93
|
-
|
94
|
+
decoded_captcha = self.captcha(decoded_captcha.id)
|
94
95
|
raise DeathByCaptcha::Timeout if (Time.now - started_at) > self.timeout
|
95
96
|
end
|
96
97
|
|
97
|
-
raise DeathByCaptcha::IncorrectSolution if !
|
98
|
+
raise DeathByCaptcha::IncorrectSolution if !decoded_captcha.is_correct
|
98
99
|
|
99
|
-
|
100
|
+
decoded_captcha
|
100
101
|
end
|
101
102
|
|
102
103
|
# Retrieve information from an uploaded captcha.
|
@@ -53,8 +53,20 @@ module DeathByCaptcha
|
|
53
53
|
#
|
54
54
|
# @return [DeathByCaptcha::Captcha] The captcha object (not solved yet).
|
55
55
|
#
|
56
|
-
def upload(
|
57
|
-
|
56
|
+
def upload(options = {})
|
57
|
+
payload = {}
|
58
|
+
payload[:captchafile] = "base64:#{options[:raw64]}"
|
59
|
+
payload[:type] = options[:type] if options[:type].to_i > 0
|
60
|
+
|
61
|
+
if options[:type].to_i == 3
|
62
|
+
banner64 = load_captcha(options[:banner])
|
63
|
+
raise DeathByCaptcha::InvalidCaptcha if banner64.to_s.empty?
|
64
|
+
|
65
|
+
payload[:banner] = "base64:#{banner64}"
|
66
|
+
payload[:banner_text] = options[:banner_text].to_s
|
67
|
+
end
|
68
|
+
|
69
|
+
response = perform('captcha', :post_multipart, payload)
|
58
70
|
DeathByCaptcha::Captcha.new(response)
|
59
71
|
end
|
60
72
|
|
@@ -84,7 +96,6 @@ module DeathByCaptcha
|
|
84
96
|
boundary, body = prepare_multipart_data(payload)
|
85
97
|
req.content_type = "multipart/form-data; boundary=#{boundary}"
|
86
98
|
req.body = body
|
87
|
-
|
88
99
|
else
|
89
100
|
uri = URI("#{BASE_URL}/#{action}?#{URI.encode_www_form(payload)}")
|
90
101
|
req = Net::HTTP::Get.new(uri.request_uri, headers)
|
@@ -54,8 +54,12 @@ module DeathByCaptcha
|
|
54
54
|
#
|
55
55
|
# @return [DeathByCaptcha::Captcha] The captcha object (not solved yet).
|
56
56
|
#
|
57
|
-
def upload(
|
58
|
-
|
57
|
+
def upload(options = {})
|
58
|
+
if options[:type] && options[:type].to_i != 1
|
59
|
+
# Socket client implementation currently supports only text captchas.
|
60
|
+
raise DeathByCaptcha::InvalidCaptcha
|
61
|
+
end
|
62
|
+
response = perform('upload', captcha: options[:raw64])
|
59
63
|
DeathByCaptcha::Captcha.new(response)
|
60
64
|
end
|
61
65
|
|
@@ -0,0 +1,56 @@
|
|
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
|
+
|
10
|
+
describe 'Solving an image based captcha' do
|
11
|
+
before(:all) { @client = DeathByCaptcha.new(username, password, :http) }
|
12
|
+
|
13
|
+
context 'Coordinates API' do
|
14
|
+
describe '#decode!' do
|
15
|
+
before(:all) { @captcha = @client.decode!(type: 2, path: path2) }
|
16
|
+
it { expect(@captcha).to be_a(DeathByCaptcha::Captcha) }
|
17
|
+
it { expect(@captcha.text).to match(/\A\[\[.*\]\]\Z/) }
|
18
|
+
it { expect(@captcha.coordinates).to be_a(Array) }
|
19
|
+
it { expect(@captcha.coordinates.size).to be > 0 }
|
20
|
+
it 'expect coordinates to be valid' do
|
21
|
+
@captcha.coordinates.each do |coordinate|
|
22
|
+
expect(coordinate).to be_a(Array)
|
23
|
+
expect(coordinate.size).to eq(2)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
it { expect(@captcha.is_correct).to be true }
|
27
|
+
it { expect(@captcha.id).to be > 0 }
|
28
|
+
it { expect(@captcha.id).to eq(@captcha.captcha) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'Image Group API' do
|
33
|
+
describe '#decode!' do
|
34
|
+
before(:all) do
|
35
|
+
@captcha = @client.decode!(
|
36
|
+
type: 3,
|
37
|
+
path: path3_grid,
|
38
|
+
banner: { path: path3_banner },
|
39
|
+
banner_text: banner_text3
|
40
|
+
)
|
41
|
+
end
|
42
|
+
it { expect(@captcha).to be_a(DeathByCaptcha::Captcha) }
|
43
|
+
it { expect(@captcha.text).to match(/\A\[.*\]\Z/) }
|
44
|
+
it { expect(@captcha.indexes).to be_a(Array) }
|
45
|
+
it { expect(@captcha.indexes.size).to be > 0 }
|
46
|
+
it 'expect indexes to be valid' do
|
47
|
+
@captcha.indexes.each do |index|
|
48
|
+
expect(index).to be_a(Numeric)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
it { expect(@captcha.is_correct).to be true }
|
52
|
+
it { expect(@captcha.id).to be > 0 }
|
53
|
+
it { expect(@captcha.id).to eq(@captcha.captcha) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
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.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Débora Setton Fernandes, Rafael Barbolo, Rafael Ivan Garcia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -55,7 +55,9 @@ dependencies:
|
|
55
55
|
description: DeathByCaptcha allows you to solve captchas with manual labor
|
56
56
|
email:
|
57
57
|
- team@infosimples.com.br
|
58
|
-
executables:
|
58
|
+
executables:
|
59
|
+
- console
|
60
|
+
- setup
|
59
61
|
extensions: []
|
60
62
|
extra_rdoc_files: []
|
61
63
|
files:
|
@@ -65,7 +67,12 @@ files:
|
|
65
67
|
- LICENSE.txt
|
66
68
|
- README.md
|
67
69
|
- Rakefile
|
70
|
+
- bin/console
|
71
|
+
- bin/setup
|
68
72
|
- captchas/1.png
|
73
|
+
- captchas/2.jpg
|
74
|
+
- captchas/3-banner.jpg
|
75
|
+
- captchas/3-grid.jpg
|
69
76
|
- deathbycaptcha.gemspec
|
70
77
|
- lib/deathbycaptcha.rb
|
71
78
|
- lib/deathbycaptcha/client.rb
|
@@ -80,6 +87,7 @@ files:
|
|
80
87
|
- lib/deathbycaptcha/version.rb
|
81
88
|
- spec/credentials.yml.example
|
82
89
|
- spec/lib/client_spec.rb
|
90
|
+
- spec/lib/image_captcha_spec.rb
|
83
91
|
- spec/spec_helper.rb
|
84
92
|
homepage: https://github.com/infosimples/deathbycaptcha
|
85
93
|
licenses:
|
@@ -108,4 +116,5 @@ summary: Ruby API for DeathByCaptcha (Captcha Solver as a Service)
|
|
108
116
|
test_files:
|
109
117
|
- spec/credentials.yml.example
|
110
118
|
- spec/lib/client_spec.rb
|
119
|
+
- spec/lib/image_captcha_spec.rb
|
111
120
|
- spec/spec_helper.rb
|