deathbycaptcha 4.1.5 → 5.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 +17 -4
- data/CHANGELOG.md +20 -0
- data/Gemfile +1 -1
- data/{MIT-LICENSE → LICENSE.txt} +4 -2
- data/README.md +132 -51
- data/Rakefile +2 -2
- data/captchas/1.png +0 -0
- data/deathbycaptcha.gemspec +21 -21
- data/lib/deathbycaptcha.rb +11 -6
- data/lib/deathbycaptcha/client.rb +143 -129
- data/lib/deathbycaptcha/client/http.rb +135 -0
- data/lib/deathbycaptcha/client/socket.rb +113 -0
- data/lib/deathbycaptcha/exceptions.rb +62 -0
- data/lib/deathbycaptcha/models.rb +16 -0
- data/lib/deathbycaptcha/models/captcha.rb +20 -0
- data/lib/deathbycaptcha/models/server_status.rb +20 -0
- data/lib/deathbycaptcha/models/user.rb +28 -0
- data/lib/deathbycaptcha/patches.rb +9 -0
- data/lib/deathbycaptcha/version.rb +3 -3
- data/spec/credentials.yml.example +3 -0
- data/spec/lib/client_spec.rb +94 -0
- data/spec/spec_helper.rb +21 -0
- metadata +59 -39
- data/lib/deathbycaptcha/config.rb +0 -42
- data/lib/deathbycaptcha/errors.rb +0 -69
- data/lib/deathbycaptcha/http_client.rb +0 -98
- data/lib/deathbycaptcha/socket_client.rb +0 -224
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
# Run specs in random order to surface order dependencies. If you find an
|
3
|
+
# order dependency and want to debug it, you can fix the order by providing
|
4
|
+
# the seed, which is printed after each run.
|
5
|
+
# --seed 1234
|
6
|
+
config.order = "random"
|
7
|
+
|
8
|
+
# Print tests results with color.
|
9
|
+
config.color = true
|
10
|
+
|
11
|
+
# Only accept the new syntax of "expect" instead of "should".
|
12
|
+
config.expect_with :rspec do |c|
|
13
|
+
c.syntax = :expect
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'yaml'
|
18
|
+
require 'deathbycaptcha'
|
19
|
+
|
20
|
+
|
21
|
+
CREDENTIALS = YAML.load_file('spec/credentials.yml')
|
metadata
CHANGED
@@ -1,91 +1,111 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deathbycaptcha
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 5.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
|
-
- Rafael Barbolo
|
7
|
+
- Débora Setton Fernandes, Rafael Barbolo, Rafael Ivan Garcia
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2015-01-26 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
14
|
+
name: bundler
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.
|
22
|
-
type: :
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: 1.
|
26
|
+
version: '1.7'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
|
-
name:
|
28
|
+
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - "~>"
|
36
32
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
38
|
-
type: :
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - "~>"
|
44
39
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
46
|
-
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.1'
|
55
|
+
description: DeathByCaptcha allows you to solve captchas with manual labor
|
47
56
|
email:
|
48
|
-
-
|
57
|
+
- team@infosimples.com.br
|
49
58
|
executables: []
|
50
59
|
extensions: []
|
51
60
|
extra_rdoc_files: []
|
52
61
|
files:
|
53
|
-
- .gitignore
|
62
|
+
- ".gitignore"
|
63
|
+
- CHANGELOG.md
|
54
64
|
- Gemfile
|
55
|
-
-
|
65
|
+
- LICENSE.txt
|
56
66
|
- README.md
|
57
67
|
- Rakefile
|
68
|
+
- captchas/1.png
|
58
69
|
- deathbycaptcha.gemspec
|
59
70
|
- lib/deathbycaptcha.rb
|
60
71
|
- lib/deathbycaptcha/client.rb
|
61
|
-
- lib/deathbycaptcha/
|
62
|
-
- lib/deathbycaptcha/
|
63
|
-
- lib/deathbycaptcha/
|
64
|
-
- lib/deathbycaptcha/
|
72
|
+
- lib/deathbycaptcha/client/http.rb
|
73
|
+
- lib/deathbycaptcha/client/socket.rb
|
74
|
+
- lib/deathbycaptcha/exceptions.rb
|
75
|
+
- lib/deathbycaptcha/models.rb
|
76
|
+
- lib/deathbycaptcha/models/captcha.rb
|
77
|
+
- lib/deathbycaptcha/models/server_status.rb
|
78
|
+
- lib/deathbycaptcha/models/user.rb
|
79
|
+
- lib/deathbycaptcha/patches.rb
|
65
80
|
- lib/deathbycaptcha/version.rb
|
66
|
-
|
67
|
-
|
81
|
+
- spec/credentials.yml.example
|
82
|
+
- spec/lib/client_spec.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
homepage: https://github.com/infosimples/deathbycaptcha
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
metadata: {}
|
68
88
|
post_install_message:
|
69
89
|
rdoc_options: []
|
70
90
|
require_paths:
|
71
91
|
- lib
|
72
92
|
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
93
|
requirements:
|
75
|
-
- -
|
94
|
+
- - ">="
|
76
95
|
- !ruby/object:Gem::Version
|
77
96
|
version: '0'
|
78
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
-
none: false
|
80
98
|
requirements:
|
81
|
-
- -
|
99
|
+
- - ">="
|
82
100
|
- !ruby/object:Gem::Version
|
83
101
|
version: '0'
|
84
102
|
requirements: []
|
85
|
-
rubyforge_project:
|
86
|
-
rubygems_version:
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 2.4.3
|
87
105
|
signing_key:
|
88
|
-
specification_version:
|
106
|
+
specification_version: 4
|
89
107
|
summary: Ruby API for DeathByCaptcha (Captcha Solver as a Service)
|
90
|
-
test_files:
|
91
|
-
|
108
|
+
test_files:
|
109
|
+
- spec/credentials.yml.example
|
110
|
+
- spec/lib/client_spec.rb
|
111
|
+
- spec/spec_helper.rb
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module DeathByCaptcha
|
2
|
-
|
3
|
-
#
|
4
|
-
# Config class
|
5
|
-
# based on http://mjijackson.com/2010/02/flexible-ruby-config-objects
|
6
|
-
#
|
7
|
-
class Config
|
8
|
-
|
9
|
-
def initialize(data = {})
|
10
|
-
@data = {}
|
11
|
-
update!(data)
|
12
|
-
end
|
13
|
-
|
14
|
-
def update!(data)
|
15
|
-
data.each do |key, value|
|
16
|
-
self[key] = value
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def [](key)
|
21
|
-
@data[key.to_sym]
|
22
|
-
end
|
23
|
-
|
24
|
-
def []=(key, value)
|
25
|
-
if value.class == Hash
|
26
|
-
@data[key.to_sym] = Config.new(value)
|
27
|
-
else
|
28
|
-
@data[key.to_sym] = value
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def method_missing(sym, *args)
|
33
|
-
if sym.to_s =~ /(.+)=$/
|
34
|
-
self[$1] = args.first
|
35
|
-
else
|
36
|
-
self[sym]
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
module DeathByCaptcha
|
2
|
-
|
3
|
-
module Errors
|
4
|
-
|
5
|
-
#
|
6
|
-
# Custom Error class for rescuing from DeathByCaptcha API errors.
|
7
|
-
#
|
8
|
-
class Error < StandardError
|
9
|
-
|
10
|
-
def initialize(message)
|
11
|
-
super("#{message} (DEATHBYCAPTCHA API ERROR)")
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
#
|
17
|
-
# Raised when a method tries to access a not implemented method.
|
18
|
-
#
|
19
|
-
class NotImplemented < Error
|
20
|
-
def initialize
|
21
|
-
super('The requested functionality was not implemented')
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
#
|
26
|
-
# Raised when a HTTP call fails.
|
27
|
-
#
|
28
|
-
class CallError < Error
|
29
|
-
def initialize
|
30
|
-
super('HTTP call failed')
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
#
|
35
|
-
# Raised when the user is not allowed to access the API.
|
36
|
-
#
|
37
|
-
class AccessDenied < Error
|
38
|
-
def initialize
|
39
|
-
super('Access denied, please check your credentials and/or balance')
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
#
|
44
|
-
# Raised when the captcha file could not be loaded or is empty.
|
45
|
-
#
|
46
|
-
class CaptchaEmpty < Error
|
47
|
-
def initialize
|
48
|
-
super('CAPTCHA image is empty or could not be loaded')
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
#
|
53
|
-
# Raised when the size of the captcha file is too big.
|
54
|
-
#
|
55
|
-
class CaptchaOverflow < Error
|
56
|
-
def initialize
|
57
|
-
super('CAPTCHA image is too big')
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
class ServiceOverload < Error
|
62
|
-
def initialize
|
63
|
-
super('CAPTCHA was rejected due to service overload, try again later')
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
require 'rest_client'
|
2
|
-
require 'json'
|
3
|
-
require 'digest/md5'
|
4
|
-
|
5
|
-
module DeathByCaptcha
|
6
|
-
|
7
|
-
#
|
8
|
-
# DeathByCaptcha HTTP API client
|
9
|
-
#
|
10
|
-
class HTTPClient < DeathByCaptcha::Client
|
11
|
-
|
12
|
-
def get_user
|
13
|
-
call('user', userpwd)
|
14
|
-
end
|
15
|
-
|
16
|
-
def get_captcha(cid)
|
17
|
-
call("captcha/#{cid}")
|
18
|
-
end
|
19
|
-
|
20
|
-
def report(cid)
|
21
|
-
call("captcha/#{cid}/report", userpwd)['is_correct']
|
22
|
-
end
|
23
|
-
|
24
|
-
def remove(cid)
|
25
|
-
not call("captcha/#{cid}/remove", userpwd)['captcha']
|
26
|
-
end
|
27
|
-
|
28
|
-
#
|
29
|
-
# Protected methods.
|
30
|
-
#
|
31
|
-
protected
|
32
|
-
|
33
|
-
def upload(captcha, options = {})
|
34
|
-
options = {
|
35
|
-
:is_case_sensitive => false,
|
36
|
-
:is_raw_content => false
|
37
|
-
}.merge(options)
|
38
|
-
|
39
|
-
data = userpwd
|
40
|
-
data[:swid] = config.software_vendor_id
|
41
|
-
data[:is_case_sensitive] = (options[:is_case_sensitive] ? 1 : 0)
|
42
|
-
data[:captchafile] = load_file(captcha, options[:is_raw_content], options[:headers])
|
43
|
-
response = call('captcha', data)
|
44
|
-
|
45
|
-
return response if response['captcha']
|
46
|
-
end
|
47
|
-
|
48
|
-
#
|
49
|
-
# Private methods.
|
50
|
-
#
|
51
|
-
private
|
52
|
-
|
53
|
-
def call(cmd, payload = {}, headers = {})
|
54
|
-
|
55
|
-
headers = {} unless headers.is_a?(Hash)
|
56
|
-
headers['Accept'] = config.http_response_type if headers['Accept'].nil?
|
57
|
-
headers['User-Agent'] = config.api_version if headers['User-Agent'].nil?
|
58
|
-
|
59
|
-
log('SEND', "#{cmd} #{payload}")
|
60
|
-
|
61
|
-
begin
|
62
|
-
url = "#{config.http_base_url}/#{cmd}"
|
63
|
-
|
64
|
-
if payload.empty?
|
65
|
-
response = RestClient.get(url, headers)
|
66
|
-
else
|
67
|
-
response = RestClient.post(url, payload, headers)
|
68
|
-
end
|
69
|
-
|
70
|
-
log('RECV', "#{response.size} #{response}")
|
71
|
-
|
72
|
-
return JSON.load(response)
|
73
|
-
|
74
|
-
rescue RestClient::Unauthorized => exc
|
75
|
-
raise DeathByCaptcha::Errors::AccessDenied
|
76
|
-
|
77
|
-
rescue RestClient::RequestFailed => exc
|
78
|
-
raise DeathByCaptcha::Errors::CallError
|
79
|
-
|
80
|
-
rescue RestClient::ServiceUnavailable => exc
|
81
|
-
raise DeathByCaptcha::Errors::ServiceOverload
|
82
|
-
|
83
|
-
else
|
84
|
-
raise DeathByCaptcha::Errors::CallError
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
return {}
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.http_client(username, password, extra = {})
|
95
|
-
DeathByCaptcha::HTTPClient.new(username, password, extra)
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
@@ -1,224 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'digest/md5'
|
3
|
-
require 'thread'
|
4
|
-
require 'socket'
|
5
|
-
require 'base64'
|
6
|
-
|
7
|
-
module DeathByCaptcha
|
8
|
-
|
9
|
-
#
|
10
|
-
# DeathByCaptcha Socket API client
|
11
|
-
#
|
12
|
-
class SocketClient < DeathByCaptcha::Client
|
13
|
-
|
14
|
-
def initialize(username, password, extra = {})
|
15
|
-
@mutex = Mutex.new
|
16
|
-
@socket = nil
|
17
|
-
|
18
|
-
super(username, password, extra)
|
19
|
-
end
|
20
|
-
|
21
|
-
def get_user
|
22
|
-
call('user')
|
23
|
-
end
|
24
|
-
|
25
|
-
def get_captcha(cid)
|
26
|
-
call('captcha', { :captcha => cid })
|
27
|
-
end
|
28
|
-
|
29
|
-
def report(cid)
|
30
|
-
call('report', { :captcha => cid })[:is_correct]
|
31
|
-
end
|
32
|
-
|
33
|
-
#
|
34
|
-
# Protected methods.
|
35
|
-
#
|
36
|
-
protected
|
37
|
-
|
38
|
-
def upload(captcha, is_case_sensitive = false, is_raw_content = false)
|
39
|
-
data = {
|
40
|
-
:captcha => Base64.encode64(load_file(captcha, is_raw_content).read),
|
41
|
-
:is_case_sensitive => (is_case_sensitive ? 1 : 0)
|
42
|
-
}
|
43
|
-
|
44
|
-
call('upload', data)
|
45
|
-
end
|
46
|
-
|
47
|
-
#
|
48
|
-
# Private methods.
|
49
|
-
#
|
50
|
-
private
|
51
|
-
|
52
|
-
def connect
|
53
|
-
unless @socket
|
54
|
-
log('CONN')
|
55
|
-
begin
|
56
|
-
random_port = config.socket_ports[rand(config.socket_ports.size)]
|
57
|
-
# Creates a new Socket.
|
58
|
-
addr = Socket.pack_sockaddr_in(random_port, config.socket_host)
|
59
|
-
|
60
|
-
@socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
61
|
-
@socket.connect_nonblock(addr)
|
62
|
-
rescue Errno::EINPROGRESS
|
63
|
-
log("INPROG", 'Waiting...')
|
64
|
-
rescue Exception => e
|
65
|
-
close # Closes the socket.
|
66
|
-
log('CONN', 'Could not connect.')
|
67
|
-
log('CONN', e.backtrace.join("\n"))
|
68
|
-
raise e
|
69
|
-
end
|
70
|
-
end
|
71
|
-
@socket
|
72
|
-
end
|
73
|
-
|
74
|
-
def close
|
75
|
-
if @socket
|
76
|
-
log('CLOSE')
|
77
|
-
begin
|
78
|
-
@socket.close
|
79
|
-
rescue Exception => e
|
80
|
-
log('CLOSE', 'Could not close socket.')
|
81
|
-
log('CLOSE', e.backtrace.join("\n"))
|
82
|
-
ensure
|
83
|
-
@socket = nil
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def send(sock, buf)
|
89
|
-
# buf += '\n'
|
90
|
-
fds = [sock]
|
91
|
-
deadline = Time.now.to_f + 3 * config.polls_interval
|
92
|
-
while deadline > Time.now.to_f and not buf.empty? do
|
93
|
-
_, wr, ex = IO.select([], fds, fds, config.polls_interval)
|
94
|
-
|
95
|
-
if ex and ex.any?
|
96
|
-
raise IOError.new('send(): select() excepted')
|
97
|
-
elsif wr
|
98
|
-
while buf and not buf.empty? do
|
99
|
-
begin
|
100
|
-
sent = wr.first.send(buf, 0)
|
101
|
-
buf = buf[sent, buf.size - sent]
|
102
|
-
rescue Exception => e
|
103
|
-
if [35, 36].include? e.errno
|
104
|
-
break
|
105
|
-
else
|
106
|
-
raise e
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
unless buf.empty?
|
114
|
-
raise IOError.new('send() timed out')
|
115
|
-
else
|
116
|
-
return self
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def recv(sock)
|
121
|
-
fds = [sock]
|
122
|
-
buf = ''
|
123
|
-
|
124
|
-
deadline = Time.now.to_f() + 3 * config.polls_interval
|
125
|
-
while deadline > Time.now.to_f do
|
126
|
-
rd, _, ex = IO.select(fds, [], fds, config.polls_interval)
|
127
|
-
if ex and ex.any?
|
128
|
-
raise IOError.new('send(): select() excepted')
|
129
|
-
elsif rd
|
130
|
-
while true do
|
131
|
-
begin
|
132
|
-
s = rd.first.recv_nonblock(256)
|
133
|
-
rescue Errno::EAGAIN
|
134
|
-
break
|
135
|
-
rescue Exception => e
|
136
|
-
if [35, 36].include? e.errno
|
137
|
-
break
|
138
|
-
else
|
139
|
-
raise e
|
140
|
-
end
|
141
|
-
else
|
142
|
-
if not s
|
143
|
-
raise IOError.new('recv(): connection lost')
|
144
|
-
else
|
145
|
-
buf += s
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
break if buf.size > 0
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
return buf[0, buf.size] if buf.size > 0
|
154
|
-
raise IOError.new('recv() timed out')
|
155
|
-
end
|
156
|
-
|
157
|
-
def call(cmd, data = {})
|
158
|
-
data = {} if data.nil?
|
159
|
-
data.merge!({ :cmd => cmd, :version => config.api_version })
|
160
|
-
|
161
|
-
request = data.to_json
|
162
|
-
log('SEND', request.to_s)
|
163
|
-
|
164
|
-
response = nil
|
165
|
-
|
166
|
-
(0...1).each do
|
167
|
-
if not @socket and cmd != 'login'
|
168
|
-
call('login', userpwd)
|
169
|
-
end
|
170
|
-
|
171
|
-
# Locks other threads.
|
172
|
-
# If another thread has already acquired the lock, this thread will be locked.
|
173
|
-
@mutex.lock
|
174
|
-
|
175
|
-
begin
|
176
|
-
sock = connect
|
177
|
-
send(sock, request)
|
178
|
-
|
179
|
-
response = recv(sock)
|
180
|
-
rescue Exception => e
|
181
|
-
log('SEND', e.message)
|
182
|
-
log('SEND', e.backtrace.join("\n"))
|
183
|
-
close
|
184
|
-
else
|
185
|
-
# If no exception raised.
|
186
|
-
break
|
187
|
-
ensure
|
188
|
-
@mutex.unlock
|
189
|
-
end
|
190
|
-
|
191
|
-
end
|
192
|
-
|
193
|
-
if response.nil?
|
194
|
-
msg = 'Connection timed out during API request'
|
195
|
-
log('SEND', msg)
|
196
|
-
|
197
|
-
raise Exception.new(msg)
|
198
|
-
end
|
199
|
-
|
200
|
-
log('RECV', response.to_s)
|
201
|
-
|
202
|
-
begin
|
203
|
-
response = JSON.load(response)
|
204
|
-
rescue Exception => e
|
205
|
-
raise Exception.new('Invalid API response')
|
206
|
-
end
|
207
|
-
|
208
|
-
if 0x00 < response['status'] and 0x10 > response['status']
|
209
|
-
raise DeathByCaptcha::Errors::AccessDenied
|
210
|
-
elsif 0xff == response['status']
|
211
|
-
raise Exception.new('API server error occured')
|
212
|
-
else
|
213
|
-
return response
|
214
|
-
end
|
215
|
-
|
216
|
-
end
|
217
|
-
|
218
|
-
end
|
219
|
-
|
220
|
-
def self.socket_client(username, password, extra = {})
|
221
|
-
DeathByCaptcha::SocketClient.new(username, password, extra)
|
222
|
-
end
|
223
|
-
|
224
|
-
end
|