onetime-up 0.8.0 → 0.8.2

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: 4c1dc14a9677195dcc44ddb5f2f0ab15a310c2289a143d97aa2097d62e4f056f
4
- data.tar.gz: ebb13a2e7050fffc000a18befa1d7ef456151a23f30d9dcc0d75b5ce084e20b6
3
+ metadata.gz: 85848ba4ad61c6310845ccdd2df6c048888e971c849fc1d6d640d3a3ce1a11ef
4
+ data.tar.gz: 5c9ca274b07530486ec9afdbba6eaf47afba1e69a2078b4f0bd79f4c06cea641
5
5
  SHA512:
6
- metadata.gz: 021a70dcfccc65e85f3510c02e620b351302275db33989571edb809af2956e359cbdfdf0254dd2128631c7c2751c2243b9663a97f1ee9443903cc6307ce252df
7
- data.tar.gz: 44786b8cd1a188dd8fefa88766083da6fbb000de5d44465e66ed00832dc1334b3dab2e831b7bc065395a2a1fc138745fdeef0277d9f75353b78a7ca269b6cb16
6
+ metadata.gz: da72a3d7b4673ec16948faf234370d1832d2eeb2cac2a80b77745e51feac89f1d72ee07d61e8f0888dfe4d8087d9efa07502402b887a76b9b15e8e023acea970
7
+ data.tar.gz: 9099fae30afbed57be879850097ec19641e850a40ebf51e3fab75083ef14de5a7820407fc6da345168de406566374271c08e506e7c174f3aef4beae2dfea4bef
data/CHANGELOG.md CHANGED
@@ -8,6 +8,10 @@
8
8
  - Restore `apiversion` path handling for callers that pass an API version explicitly
9
9
  - Add safer CLI response handling for changed or partial API responses
10
10
  - Accept secret URLs from root and regional onetimesecret.com hosts
11
+ - `generate` no longer hangs when stdin is an idle open pipe (e.g. ssh, cron)
12
+ - Accept secret URLs with a trailing slash
13
+ - `-H` takes precedence over `ONETIME_HOST`
14
+ - Report non-JSON API responses with their HTTP status instead of a backtrace
11
15
 
12
16
  ## [0.6.0] - 2026-01-18
13
17
 
data/lib/onetime/api.rb CHANGED
@@ -146,7 +146,7 @@ module Onetime
146
146
  return value unless uri.host && uri.path
147
147
  return value unless accepted_secret_host?(uri.host, api_base_uri)
148
148
 
149
- match = uri.path.match(%r{\A/secret/([a-zA-Z0-9]+)\z})
149
+ match = uri.path.match(%r{\A/secret/([a-zA-Z0-9]+)/?\z})
150
150
  match ? match[1] : value
151
151
  rescue URI::InvalidURIError
152
152
  value
@@ -78,6 +78,24 @@ module Onetime
78
78
 
79
79
  def global_option_parser
80
80
  OptionParser.new do |opts|
81
+ opts.banner = 'Usage: onetime [options] [command] [command options] [arguments]'
82
+ opts.separator ''
83
+ opts.separator 'Commands:'
84
+ opts.separator ' share [FILE ...] Share files or stdin (default command)'
85
+ opts.separator ' generate Generate a random secret'
86
+ opts.separator ' secret KEY|URL Retrieve a secret (alias: get)'
87
+ opts.separator ' receipt KEY Retrieve receipt metadata'
88
+ opts.separator ' status Show service status'
89
+ opts.separator ''
90
+ opts.separator 'Use onetime COMMAND --help for command options.'
91
+ opts.separator ''
92
+ opts.separator 'Examples:'
93
+ opts.separator ' onetime share message.txt'
94
+ opts.separator ' echo "a secret" | onetime share'
95
+ opts.separator ' onetime generate -t 3600'
96
+ opts.separator ' onetime secret https://eu.onetimesecret.com/secret/KEY'
97
+ opts.separator ''
98
+ opts.separator 'Global options:'
81
99
  opts.on('-H BASE_URI', String) { |v| @base_uri = v }
82
100
  opts.on('-c CUSTID', '--custid CUSTID', String) { |v| @custid = v }
83
101
  opts.on('-k APIKEY', '--apikey APIKEY', String) { |v| @apikey = v }
@@ -88,12 +106,25 @@ module Onetime
88
106
  opts.on('-s', '--string') { @string_flag = true }
89
107
  opts.on('-D', '--debug') { @debug = true }
90
108
  opts.on('-V', '--version') { @show_version = true }
109
+ opts.on('-h', '--help', 'Show this help') { puts opts; exit }
91
110
  end
92
111
  end
93
112
 
94
113
  def command_option_parser(command)
95
114
  allowed = COMMAND_OPTIONS.fetch(command, [])
96
115
  OptionParser.new do |opts|
116
+ arguments = case command
117
+ when 'share' then ' [FILE ...]'
118
+ when 'secret' then ' KEY|URL'
119
+ when 'receipt' then ' KEY'
120
+ else ''
121
+ end
122
+ opts.banner = "Usage: onetime [global options] #{command} [options]#{arguments}"
123
+ if command == 'share'
124
+ opts.separator 'Reads stdin when no file is given; use - as a filename to read stdin.'
125
+ end
126
+ opts.separator ''
127
+ opts.separator 'Options:'
97
128
  if allowed.include?(:ttl)
98
129
  opts.on('-t TTL', '--ttl TTL', Integer) { |v| @ttl = v }
99
130
  end
@@ -103,6 +134,7 @@ module Onetime
103
134
  if allowed.include?(:recipient)
104
135
  opts.on('-r RECIPIENT', '--recipient RECIPIENT', Array) { |v| @command_recipients.concat(Array(v)) }
105
136
  end
137
+ opts.on('-h', '--help', 'Show this help') { puts opts; exit }
106
138
  end
107
139
  end
108
140
 
@@ -41,9 +41,10 @@ module Onetime
41
41
  end
42
42
 
43
43
  def configure_api!
44
- OT::API.base_uri @parsed.base_uri if @parsed.base_uri
45
44
  OT::API.debug_output @stderr if @parsed.debug
46
45
  @api = OT::API.new(@parsed.custid, @parsed.apikey)
46
+ # Set after API.new, which applies ONETIME_HOST, so that -H takes precedence.
47
+ OT::API.base_uri @parsed.base_uri if @parsed.base_uri
47
48
  end
48
49
 
49
50
  def run_status
@@ -119,7 +120,8 @@ module Onetime
119
120
  extras = @parsed.argv
120
121
  raise Error, "generate takes no arguments (got: %s). Did you mean: onetime share < %s" % [extras.join(' '), extras.first]
121
122
  end
122
- if !@stdin.tty? && !@stdin.eof?
123
+ # Non-blocking check: an idle pipe that is never closed (ssh, cron) must not hang.
124
+ if !@stdin.tty? && IO.select([@stdin], nil, nil, 0) && !@stdin.eof?
123
125
  raise Error, 'generate does not read stdin. Did you mean: onetime share'
124
126
  end
125
127
  opts = { ttl: @parsed.ttl, recipient: @parsed.recipients }
@@ -189,15 +191,19 @@ module Onetime
189
191
  end
190
192
 
191
193
  def api_get(path)
192
- res = @api.get(path)
193
- check_response!(res)
194
- res
194
+ request { @api.get(path) }
195
195
  end
196
196
 
197
197
  def api_post(path, params)
198
- res = @api.post(path, params)
198
+ request { @api.post(path, params) }
199
+ end
200
+
201
+ def request
202
+ res = yield
199
203
  check_response!(res)
200
204
  res
205
+ rescue JSON::ParserError
206
+ raise Error, "Unexpected non-JSON response (HTTP #{@api.response.code})"
201
207
  end
202
208
 
203
209
  def check_response!(res)
@@ -1,3 +1,3 @@
1
1
  module Onetime
2
- VERSION = "0.8.0"
2
+ VERSION = "0.8.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: onetime-up
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
8
8
  - Saverio Miroddi
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-13 00:00:00.000000000 Z
11
+ date: 2026-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -91,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
91
  - !ruby/object:Gem::Version
92
92
  version: 2.0.0
93
93
  requirements: []
94
- rubygems_version: 4.0.9
94
+ rubygems_version: 4.0.20
95
95
  specification_version: 4
96
96
  summary: Command-line tool and library for onetimesecret.com API (API v2)
97
97
  test_files: []