private_captcha 0.0.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e0681aaa5e68aae1562fbe7fc20c19dc098305f752673f574e50c6c0094fcb95
4
- data.tar.gz: 12c1a1692cd0b3d3be4d775fcebf95389a5fc8d40cfa0fec39783e6f8bc4f06d
3
+ metadata.gz: 633ba6ed9f1e744f7198bb02c280a219ee4cf88773b68507c6eec0a43e4b9ac7
4
+ data.tar.gz: 2fa1a08ffc72014ca32080b52fcd71bf2427c25c11ff1f0901c549350d28e1b9
5
5
  SHA512:
6
- metadata.gz: fc9382338a62a9cb3d5f49ead2b670bcf3967eae7051308c20cbe436fdbf3046f1177df9a1e2b723ea1e8560b5343e04bfd8288b9da1bc20e9c5bf5b38973a5e
7
- data.tar.gz: 33e903e9de21aba85e9cb34a12015555ed30fc415118c2923495f75f0373bf64d91b9cda145b9936447a8f17c46d979c150fc01c16f9fd2685cc0d8e4661feed
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
- ![CI](https://github.com/PrivateCaptcha/private-captcha-ruby/actions/workflows/ci.yaml/badge.svg)
3
+ [![Gem Version](https://badge.fury.io/rb/private_captcha.svg)](https://badge.fury.io/rb/private_captcha)
4
+ ![CI](https://github.com/PrivateCaptcha/private-captcha-ruby/actions/workflows/ci.yaml/badge.svg)
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
- raise Error, "captcha verification failed: #{output.error_message}" unless output.success
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, status_code
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, request_id: request_id)
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
- class Error < StandardError; end
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 :request_id, :attempt
36
+ attr_reader :trace_id, :attempt
37
37
 
38
- def initialize(success: false, code: VERIFY_NO_ERROR, origin: nil, timestamp: nil, request_id: nil, attempt: 0)
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
- @request_id = request_id
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, request_id: nil, attempt: 0)
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
- request_id: request_id,
57
+ trace_id: trace_id,
58
58
  attempt: attempt
59
59
  )
60
60
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PrivateCaptcha
4
- VERSION = '0.0.2'
4
+ VERSION = '0.0.3'
5
5
  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.2
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-26 00:00:00.000000000 Z
11
+ date: 2025-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -46,6 +46,7 @@ licenses:
46
46
  metadata:
47
47
  homepage_uri: https://privatecaptcha.com
48
48
  source_code_uri: https://github.com/PrivateCaptcha/private-captcha-ruby
49
+ rubygems_mfa_required: 'true'
49
50
  post_install_message:
50
51
  rdoc_options: []
51
52
  require_paths:
@@ -61,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
62
  - !ruby/object:Gem::Version
62
63
  version: '0'
63
64
  requirements: []
64
- rubygems_version: 3.4.20
65
+ rubygems_version: 3.4.19
65
66
  signing_key:
66
67
  specification_version: 4
67
68
  summary: Ruby client for server-side Private Captcha API