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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d578d0181a5e858098bc2329884daff5971f7bbd
4
- data.tar.gz: b2681b030c07099cc78cb52dfc4382c6015d64b6
3
+ metadata.gz: 98c633b9bb114866ddf802c7420e8c44d737dffd
4
+ data.tar.gz: f940fb9797a688edebe3b90da31dbff445c1a27a
5
5
  SHA512:
6
- metadata.gz: 1eaf72f64a8b7e83d4e7b6933d17d3d48ea14a890cae901c1aa1f3e9693f7bbdac4e85ad23ba075010714a166946668fb60cd8032aa4d3814a31cf228e80a66c
7
- data.tar.gz: 2628bb9faeba7ee4e1438d307d3a20357bb69f3b2195afbf804add2c9d1979f48ddbc719c6f01d084e38572c76ec03b7d623f56d96733eec784d96a5e056a327
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 the image to raw64 (binary base64 encoded).
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
+ ![Example of a captcha based on image clicks](captchas/2.jpg)
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
+ ![Example of a grid of a captcha based on image clicks](captchas/3-grid.jpg)
158
+
159
+ **Captcha: banner**
160
+
161
+ ![Example of a banner of a captcha based on image clicks](captchas/3-banner.jpg)
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
- memmory and avoid conflicts with other gems.
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, memmory and IO).
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
 
@@ -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
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
Binary file
Binary file
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
- _captcha = self.upload(raw64)
91
- while _captcha.text.to_s.empty?
90
+ decoded_captcha = self.upload(options.merge(raw64: raw64))
91
+
92
+ while decoded_captcha.text.to_s.empty?
92
93
  sleep(self.polling)
93
- _captcha = self.captcha(_captcha.id)
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 !_captcha.is_correct
98
+ raise DeathByCaptcha::IncorrectSolution if !decoded_captcha.is_correct
98
99
 
99
- _captcha
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(raw64)
57
- response = perform('captcha', :post_multipart, captchafile: "base64:#{raw64}")
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(raw64)
58
- response = perform('upload', captcha: raw64)
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
 
@@ -16,5 +16,13 @@ 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
19
27
  end
20
28
  end
@@ -1,4 +1,4 @@
1
1
  module DeathByCaptcha
2
- VERSION = "5.0.2"
2
+ VERSION = "5.0.3"
3
3
  API_VERSION = "DBC/Ruby v#{VERSION}"
4
4
  end
@@ -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.2
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-05-26 00:00:00.000000000 Z
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