private_captcha 0.0.1 → 0.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 +2 -1
- data/lib/private_captcha/client.rb +14 -7
- data/lib/private_captcha/errors.rb +19 -7
- data/lib/private_captcha/verify_output.rb +5 -5
- data/lib/private_captcha/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 633ba6ed9f1e744f7198bb02c280a219ee4cf88773b68507c6eec0a43e4b9ac7
|
|
4
|
+
data.tar.gz: 2fa1a08ffc72014ca32080b52fcd71bf2427c25c11ff1f0901c549350d28e1b9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a25c0fb6454a60031b33d35e4550c6f6d7afe3ec8789cda95257926c28b3858c7f2864b753670f024aa0aa1b624ce0bd81482d6311323e9190b50001893765ab
|
|
7
|
+
data.tar.gz: 8bd7a36ace7a8e3d0ebfaf279e13661061e615ec6164413fcdc6fa2ad7e8681b4a632cf6e7ae258d1491d9f1faddbd50dcd664b1c5c6cc94da102d6f9bf2d15d
|
data/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# private-captcha-ruby
|
|
2
2
|
|
|
3
|
-
](https://badge.fury.io/rb/private_captcha)
|
|
4
|
+

|
|
4
5
|
|
|
5
6
|
Ruby client for server-side verification of Private Captcha solutions.
|
|
6
7
|
|
|
@@ -38,6 +38,7 @@ module PrivateCaptcha
|
|
|
38
38
|
response = nil
|
|
39
39
|
error = nil
|
|
40
40
|
attempt = 0
|
|
41
|
+
trace_id = nil
|
|
41
42
|
|
|
42
43
|
max_attempts.times do |i|
|
|
43
44
|
attempt = i + 1
|
|
@@ -56,6 +57,7 @@ module PrivateCaptcha
|
|
|
56
57
|
break
|
|
57
58
|
rescue RetriableError => e
|
|
58
59
|
error = e.original_error
|
|
60
|
+
trace_id = e.trace_id if e.trace_id
|
|
59
61
|
end
|
|
60
62
|
end
|
|
61
63
|
|
|
@@ -65,7 +67,8 @@ module PrivateCaptcha
|
|
|
65
67
|
|
|
66
68
|
if error
|
|
67
69
|
@logger.error("Failed to verify solution after #{attempt} attempts")
|
|
68
|
-
raise VerificationFailedError.new("Failed to verify solution after #{attempt} attempts", attempt
|
|
70
|
+
raise VerificationFailedError.new("Failed to verify solution after #{attempt} attempts", attempt,
|
|
71
|
+
trace_id: trace_id)
|
|
69
72
|
end
|
|
70
73
|
|
|
71
74
|
response
|
|
@@ -78,7 +81,10 @@ module PrivateCaptcha
|
|
|
78
81
|
|
|
79
82
|
output = verify(solution)
|
|
80
83
|
|
|
81
|
-
|
|
84
|
+
unless output.success
|
|
85
|
+
raise Error.new("captcha verification failed: #{output.error_message}",
|
|
86
|
+
trace_id: output.trace_id)
|
|
87
|
+
end
|
|
82
88
|
|
|
83
89
|
output
|
|
84
90
|
end
|
|
@@ -104,10 +110,12 @@ module PrivateCaptcha
|
|
|
104
110
|
@logger.debug('Sending HTTP request') { "path=#{@endpoint.path} method=POST" }
|
|
105
111
|
|
|
106
112
|
response = nil
|
|
113
|
+
trace_id = nil
|
|
107
114
|
begin
|
|
108
115
|
response = Net::HTTP.start(@endpoint.hostname, @endpoint.port, use_ssl: true) do |http|
|
|
109
116
|
http.request(request)
|
|
110
117
|
end
|
|
118
|
+
trace_id = response['X-Trace-ID']
|
|
111
119
|
rescue SocketError, IOError, Timeout::Error, SystemCallError => e
|
|
112
120
|
@logger.debug('Failed to send HTTP request') { "error=#{e.message}" }
|
|
113
121
|
raise RetriableError, e
|
|
@@ -118,7 +126,6 @@ module PrivateCaptcha
|
|
|
118
126
|
end
|
|
119
127
|
|
|
120
128
|
status_code = response.code.to_i
|
|
121
|
-
request_id = response['X-Trace-ID']
|
|
122
129
|
|
|
123
130
|
case status_code
|
|
124
131
|
when 429
|
|
@@ -126,16 +133,16 @@ module PrivateCaptcha
|
|
|
126
133
|
@logger.debug('Rate limited') do
|
|
127
134
|
"retryAfter=#{retry_after} rateLimit=#{response['X-RateLimit-Limit']}"
|
|
128
135
|
end
|
|
129
|
-
raise RetriableError, HTTPError.new(status_code, retry_after)
|
|
136
|
+
raise RetriableError, HTTPError.new(status_code, retry_after, trace_id: trace_id)
|
|
130
137
|
when 500, 502, 503, 504, 408, 425
|
|
131
|
-
raise RetriableError, HTTPError.new(status_code)
|
|
138
|
+
raise RetriableError, HTTPError.new(status_code, trace_id: trace_id)
|
|
132
139
|
when 300..599
|
|
133
|
-
raise HTTPError,
|
|
140
|
+
raise HTTPError.new(status_code, trace_id: trace_id)
|
|
134
141
|
end
|
|
135
142
|
|
|
136
143
|
begin
|
|
137
144
|
json_data = JSON.parse(response.body)
|
|
138
|
-
VerifyOutput.from_json(json_data,
|
|
145
|
+
VerifyOutput.from_json(json_data, trace_id: trace_id)
|
|
139
146
|
rescue JSON::ParserError => e
|
|
140
147
|
@logger.debug('Failed to parse response') { "error=#{e.message}" }
|
|
141
148
|
raise RetriableError, e
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module PrivateCaptcha
|
|
4
|
-
|
|
4
|
+
# Error is the base class for Private Captcha errors
|
|
5
|
+
class Error < StandardError
|
|
6
|
+
attr_reader :trace_id
|
|
7
|
+
|
|
8
|
+
def initialize(msg = nil, trace_id: nil)
|
|
9
|
+
@trace_id = trace_id
|
|
10
|
+
super(msg)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
5
13
|
|
|
6
14
|
# EmptyAPIKeyError is raised when the API key is not provided or is empty
|
|
7
15
|
class EmptyAPIKeyError < Error
|
|
8
|
-
def initialize(msg = 'API key is empty')
|
|
16
|
+
def initialize(msg = 'API key is empty', trace_id: nil)
|
|
9
17
|
super
|
|
10
18
|
end
|
|
11
19
|
end
|
|
12
20
|
|
|
13
21
|
# EmptySolutionError is raised when the solution is not provided or is empty
|
|
14
22
|
class EmptySolutionError < Error
|
|
15
|
-
def initialize(msg = 'solution is empty')
|
|
23
|
+
def initialize(msg = 'solution is empty', trace_id: nil)
|
|
16
24
|
super
|
|
17
25
|
end
|
|
18
26
|
end
|
|
@@ -21,10 +29,10 @@ module PrivateCaptcha
|
|
|
21
29
|
class HTTPError < Error
|
|
22
30
|
attr_reader :status_code, :seconds
|
|
23
31
|
|
|
24
|
-
def initialize(status_code, seconds = nil)
|
|
32
|
+
def initialize(status_code, seconds = nil, trace_id: nil)
|
|
25
33
|
@status_code = status_code
|
|
26
34
|
@seconds = seconds
|
|
27
|
-
super("HTTP error #{status_code}")
|
|
35
|
+
super("HTTP error #{status_code}", trace_id: trace_id)
|
|
28
36
|
end
|
|
29
37
|
end
|
|
30
38
|
|
|
@@ -36,15 +44,19 @@ module PrivateCaptcha
|
|
|
36
44
|
@original_error = error
|
|
37
45
|
super(error.message)
|
|
38
46
|
end
|
|
47
|
+
|
|
48
|
+
def trace_id
|
|
49
|
+
@original_error.respond_to?(:trace_id) ? @original_error.trace_id : nil
|
|
50
|
+
end
|
|
39
51
|
end
|
|
40
52
|
|
|
41
53
|
# VerificationFailedError is raised when verification fails after all retry attempts
|
|
42
54
|
class VerificationFailedError < Error
|
|
43
55
|
attr_reader :attempts
|
|
44
56
|
|
|
45
|
-
def initialize(message, attempts)
|
|
57
|
+
def initialize(message, attempts, trace_id: nil)
|
|
46
58
|
@attempts = attempts
|
|
47
|
-
super(message)
|
|
59
|
+
super(message, trace_id: trace_id)
|
|
48
60
|
end
|
|
49
61
|
end
|
|
50
62
|
end
|
|
@@ -33,14 +33,14 @@ module PrivateCaptcha
|
|
|
33
33
|
}.freeze
|
|
34
34
|
|
|
35
35
|
attr_accessor :success, :code, :origin, :timestamp
|
|
36
|
-
attr_reader :
|
|
36
|
+
attr_reader :trace_id, :attempt
|
|
37
37
|
|
|
38
|
-
def initialize(success: false, code: VERIFY_NO_ERROR, origin: nil, timestamp: nil,
|
|
38
|
+
def initialize(success: false, code: VERIFY_NO_ERROR, origin: nil, timestamp: nil, trace_id: nil, attempt: 0)
|
|
39
39
|
@success = success
|
|
40
40
|
@code = code
|
|
41
41
|
@origin = origin
|
|
42
42
|
@timestamp = timestamp
|
|
43
|
-
@
|
|
43
|
+
@trace_id = trace_id
|
|
44
44
|
@attempt = attempt
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -48,13 +48,13 @@ module PrivateCaptcha
|
|
|
48
48
|
ERROR_MESSAGES.fetch(@code, 'error')
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
def self.from_json(json_data,
|
|
51
|
+
def self.from_json(json_data, trace_id: nil, attempt: 0)
|
|
52
52
|
new(
|
|
53
53
|
success: json_data['success'],
|
|
54
54
|
code: json_data['code'] || VERIFY_NO_ERROR,
|
|
55
55
|
origin: json_data['origin'],
|
|
56
56
|
timestamp: json_data['timestamp'],
|
|
57
|
-
|
|
57
|
+
trace_id: trace_id,
|
|
58
58
|
attempt: attempt
|
|
59
59
|
)
|
|
60
60
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: private_captcha
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Taras Kushnir
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-10
|
|
11
|
+
date: 2025-11-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -62,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
62
62
|
- !ruby/object:Gem::Version
|
|
63
63
|
version: '0'
|
|
64
64
|
requirements: []
|
|
65
|
-
rubygems_version: 3.4.
|
|
65
|
+
rubygems_version: 3.4.19
|
|
66
66
|
signing_key:
|
|
67
67
|
specification_version: 4
|
|
68
68
|
summary: Ruby client for server-side Private Captcha API
|