deathbycaptcha 5.0.2 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d578d0181a5e858098bc2329884daff5971f7bbd
4
- data.tar.gz: b2681b030c07099cc78cb52dfc4382c6015d64b6
2
+ SHA256:
3
+ metadata.gz: b7b0ae41ffa4cc961dc9600c23ec9f0e56bf09261fa4766ed2aa1cd686a2a09f
4
+ data.tar.gz: 87885c289fce41e9a34696514dc067b62b025a45e89f7728aaf28146beba4111
5
5
  SHA512:
6
- metadata.gz: 1eaf72f64a8b7e83d4e7b6933d17d3d48ea14a890cae901c1aa1f3e9693f7bbdac4e85ad23ba075010714a166946668fb60cd8032aa4d3814a31cf228e80a66c
7
- data.tar.gz: 2628bb9faeba7ee4e1438d307d3a20357bb69f3b2195afbf804add2c9d1979f48ddbc719c6f01d084e38572c76ec03b7d623f56d96733eec784d96a5e056a327
6
+ metadata.gz: 926bfd8b477e4d3888947bfca51521402c0f170c04fb70244b31fc9fa8aea47904f00587ea9f95fe9c9cb62c1c6780164aa59ef1bed19e0ac9e232adf01690a7
7
+ data.tar.gz: 72925f985964bf277675ebc86373871f0a3c865eb7996b0eb73bde1900d14d4d8e7b3765d1ced32979c0baae3bed7d762ca8d56de9273ed48e3d42e4452c5251
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015 Rafael Barbolo
1
+ Copyright (c) 2015 Infosimples
2
2
 
3
3
  MIT License
4
4
 
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
- and [Ruby on Rails development](https://infosimples.com/en/software-development).
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 the image to raw64 (binary base64 encoded).
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
+ ![Example of a captcha based on image clicks](captchas/2.jpg)
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
+ ![Example of a grid of a captcha based on image clicks](captchas/3-grid.jpg)
164
+
165
+ **Captcha: banner**
166
+
167
+ ![Example of a banner of a captcha based on image clicks](captchas/3-banner.jpg)
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
- memmory and avoid conflicts with other gems.
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, memmory and IO).
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 )
@@ -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
@@ -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 = ["Débora Setton Fernandes, Rafael Barbolo, Rafael Ivan Garcia"]
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
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
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
 
@@ -1,4 +1,5 @@
1
1
  require 'base64'
2
+ require 'openssl'
2
3
  require 'json'
3
4
  require 'bigdecimal'
4
5
  require 'socket'
@@ -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
- raw64 = load_captcha(options)
88
- raise DeathByCaptcha::InvalidCaptcha if raw64.to_s.empty?
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
- _captcha = self.upload(raw64)
91
- while _captcha.text.to_s.empty?
98
+ while decoded_captcha.text.to_s.empty?
92
99
  sleep(self.polling)
93
- _captcha = self.captcha(_captcha.id)
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 !_captcha.is_correct
104
+ raise DeathByCaptcha::IncorrectSolution if !decoded_captcha.is_correct
98
105
 
99
- _captcha
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(raw64)
57
- response = perform('captcha', :post_multipart, captchafile: "base64:#{raw64}")
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("#{BASE_URL}/#{action}")
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("#{BASE_URL}/#{action}")
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("#{BASE_URL}/#{action}?#{URI.encode_www_form(payload)}")
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(raw64)
58
- response = perform('upload', captcha: raw64)
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, HOST)
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
@@ -1,4 +1,4 @@
1
1
  module DeathByCaptcha
2
- VERSION = "5.0.2"
2
+ VERSION = "5.2.0"
3
3
  API_VERSION = "DBC/Ruby v#{VERSION}"
4
4
  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.2
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Débora Setton Fernandes, Rafael Barbolo, Rafael Ivan Garcia
8
- autorequire:
7
+ - Rafael Barbolo, Rafael Ivan Garcia
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-26 00:00:00.000000000 Z
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
- rubyforge_project:
104
- rubygems_version: 2.4.3
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