ratproto 0.3.1 → 0.3.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/CHANGELOG.md +11 -0
- data/lib/ratproto/cli.rb +2 -0
- data/lib/ratproto/commands/account_status.rb +45 -0
- data/lib/ratproto/commands/stream.rb +70 -21
- data/lib/ratproto/commands/stream_labels.rb +17 -8
- data/lib/ratproto/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a098c33a93bc8b33f32631f733fb3b5d3d1f3b233035d1cdbf8d397071a8d566
|
|
4
|
+
data.tar.gz: ae846bf49bca35fa4ee7fe748e8d0a05eeaf60a44f6cd687d7a0d66f61c4254f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9abf0ae89949e3e20b9f89c6b0ed9d09275a4fe55b68104c0579f6c85b6f10b7901c0dc9c884c022b8f269cf28bcfe6e07e00db9519266ab4e00bc5fab5e8b35
|
|
7
|
+
data.tar.gz: 0dfd41610d6faf493475041b065b8e688bae795bdb14c85238945ec0498a80d9ea530e7ce9e1e8fe81d7938f106c9467d100859404925000a4e58927c60a480a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
## [0.3.3] - 2026-08-17
|
|
2
|
+
|
|
3
|
+
- `stream`: added `--print-time` mode, bug fixes, unified timestamp formats
|
|
4
|
+
- added `status` command that prints account status
|
|
5
|
+
|
|
6
|
+
## [0.3.2] - 2026-07-30
|
|
7
|
+
|
|
8
|
+
- `stream`: filter by record operation type using `-o`
|
|
9
|
+
- `stream`: disable all commit messages and leave account messages by passing `-c -`
|
|
10
|
+
- `stream` & `stream-labels`: disable status messages using `-q`
|
|
11
|
+
|
|
1
12
|
## [0.3.1] - 2026-07-30
|
|
2
13
|
|
|
3
14
|
- added polyfill of `Hash#except` for Ruby 2.6
|
data/lib/ratproto/cli.rb
CHANGED
|
@@ -5,6 +5,7 @@ require 'clamp'
|
|
|
5
5
|
require_relative 'version'
|
|
6
6
|
require_relative 'ext'
|
|
7
7
|
require_relative 'commands/base'
|
|
8
|
+
require_relative 'commands/account_status'
|
|
8
9
|
require_relative 'commands/fetch'
|
|
9
10
|
require_relative 'commands/resolve'
|
|
10
11
|
require_relative 'commands/stream'
|
|
@@ -51,6 +52,7 @@ module RatProto
|
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
subcommand 'fetch', 'fetch a single record given its at:// URI', Commands::Fetch
|
|
55
|
+
subcommand 'status', 'print account status', Commands::AccountStatus
|
|
54
56
|
subcommand 'stream', 'stream events from a relay or PDS firehose', Commands::Stream
|
|
55
57
|
subcommand 'stream-labels', 'stream labels a labeller firehose', Commands::StreamLabels
|
|
56
58
|
subcommand 'resolve', 'resolve a DID or @handle', Commands::Resolve
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'didkit'
|
|
4
|
+
|
|
5
|
+
require_relative 'base'
|
|
6
|
+
|
|
7
|
+
module RatProto
|
|
8
|
+
module Commands
|
|
9
|
+
class AccountStatus < Base
|
|
10
|
+
banner 'Print status of an account on its PDS'
|
|
11
|
+
|
|
12
|
+
parameter 'TARGET', 'DID or handle'
|
|
13
|
+
|
|
14
|
+
option ['-s', '--status'], :flag, 'print only the status without a full message'
|
|
15
|
+
|
|
16
|
+
def execute
|
|
17
|
+
begin
|
|
18
|
+
resolved_did = DID.resolve_handle(target)
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
signal_error "resolving #{target.inspect}: #{e.class}: #{e.message}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if resolved_did.nil?
|
|
24
|
+
signal_error "couldn't resolve #{target}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
result = resolved_did.account_status
|
|
28
|
+
|
|
29
|
+
if status?
|
|
30
|
+
puts (result&.to_s || 'deleted')
|
|
31
|
+
return
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
case result
|
|
35
|
+
when :active
|
|
36
|
+
puts "#{resolved_did} at #{resolved_did.document.pds_host}: account active"
|
|
37
|
+
when nil
|
|
38
|
+
puts "#{resolved_did} at #{resolved_did.document.pds_host}: account not found"
|
|
39
|
+
else
|
|
40
|
+
puts "#{resolved_did} at #{resolved_did.document.pds_host}: account inactive (status = #{result})"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -9,6 +9,8 @@ require_relative 'base'
|
|
|
9
9
|
module RatProto
|
|
10
10
|
module Commands
|
|
11
11
|
class Stream < Base
|
|
12
|
+
OPERATION_TYPES = %w[create update delete].freeze
|
|
13
|
+
|
|
12
14
|
banner 'Stream events from a relay or PDS firehose'
|
|
13
15
|
|
|
14
16
|
parameter 'SERVICE', 'relay, PDS or Jetstream hostname'
|
|
@@ -26,31 +28,37 @@ module RatProto
|
|
|
26
28
|
option ['-d', '--did'], 'DID[,DID...]', 'filter events by DID (comma-separated or repeated)',
|
|
27
29
|
multivalued: true, attribute_name: :did_values
|
|
28
30
|
|
|
29
|
-
option ['-c', '--collection'], 'NSID[,NSID...]',
|
|
31
|
+
option ['-c', '--collection'], 'NSID[,NSID...]',
|
|
32
|
+
"filter events by collection (comma-separated or repeated; pass '-' to skip all and only print account events)",
|
|
30
33
|
multivalued: true, attribute_name: :collection_values
|
|
31
34
|
|
|
32
|
-
option ['-
|
|
33
|
-
|
|
35
|
+
option ['-o', '--operation'], 'ACTION[,ACTION...]',
|
|
36
|
+
'filter events by operation (create, update or delete; comma-separated or repeated)',
|
|
37
|
+
multivalued: true, attribute_name: :operation_values
|
|
38
|
+
|
|
39
|
+
option ['-a', '--[no-]account'], :flag,
|
|
40
|
+
'print account status events (default: enabled unless filtering by collection or operation)'
|
|
41
|
+
|
|
42
|
+
option ['-q', '--quiet'], :flag, 'disable status messages'
|
|
43
|
+
option ['-s', '--print-cursor'], :flag, 'only print cursor (seq) of first event and disconnect'
|
|
44
|
+
option ['--print-time'], :flag, 'only print timestamp of first event and disconnect'
|
|
34
45
|
|
|
35
46
|
|
|
36
47
|
def execute
|
|
37
48
|
require 'skyfall'
|
|
38
49
|
|
|
39
|
-
|
|
40
|
-
@collections = comma_separated(collection_values, '-c/--collection')
|
|
41
|
-
|
|
42
|
-
@dids = (@dids.length > 0) ? @dids.map { |did| map_argument_to_did(did) } : nil
|
|
43
|
-
@collections = (@collections.length > 0) ? @collections.map { |collection| validate_nsid(collection) } : nil
|
|
50
|
+
prepare_filters
|
|
44
51
|
|
|
45
52
|
@sky = build_stream
|
|
46
53
|
configure_interrupt_handler
|
|
47
54
|
|
|
48
|
-
if print_cursor?
|
|
55
|
+
if print_cursor? || print_time?
|
|
49
56
|
@sky.on_message do |msg|
|
|
50
57
|
print_cursor_and_stop(msg)
|
|
51
58
|
next
|
|
52
59
|
end
|
|
53
60
|
|
|
61
|
+
@sky.on_error { |e| report_error(e) }
|
|
54
62
|
@sky.connect
|
|
55
63
|
else
|
|
56
64
|
configure_callbacks
|
|
@@ -63,6 +71,40 @@ module RatProto
|
|
|
63
71
|
|
|
64
72
|
private
|
|
65
73
|
|
|
74
|
+
def prepare_filters
|
|
75
|
+
@dids = comma_separated(did_values, '-d/--did')
|
|
76
|
+
@collections = comma_separated(collection_values, '-c/--collection')
|
|
77
|
+
@operations = comma_separated(operation_values, '-o/--operation')
|
|
78
|
+
|
|
79
|
+
if @collections.include?('-')
|
|
80
|
+
if @collections.any? { |collection| collection != '-' }
|
|
81
|
+
signal_usage_error("'-' cannot be combined with collection names")
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if @operations.length > 0
|
|
85
|
+
signal_usage_error("'-c -' cannot be combined with -o/--operation")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
@no_collections = true
|
|
89
|
+
@collections = nil
|
|
90
|
+
elsif @collections.length > 0
|
|
91
|
+
@collections = @collections.map { |collection| validate_nsid(collection) }
|
|
92
|
+
else
|
|
93
|
+
@collections = nil
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
@dids = (@dids.length > 0) ? @dids.map { |did| map_argument_to_did(did) } : nil
|
|
97
|
+
@operations = (@operations.length > 0) ? @operations.map { |operation| validate_operation(operation) } : nil
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def validate_operation(operation)
|
|
101
|
+
if OPERATION_TYPES.include?(operation)
|
|
102
|
+
operation.to_sym
|
|
103
|
+
else
|
|
104
|
+
signal_usage_error("#{operation.inspect} is not a valid operation (expected create, update or delete)")
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
66
108
|
def build_stream
|
|
67
109
|
if jetstream?
|
|
68
110
|
options = {}
|
|
@@ -90,10 +132,10 @@ module RatProto
|
|
|
90
132
|
end
|
|
91
133
|
|
|
92
134
|
def report_error(error)
|
|
93
|
-
log "ERROR: #{error.message}"
|
|
135
|
+
log "ERROR: #{error.message}", true
|
|
94
136
|
|
|
95
137
|
if !jetstream? && error.message.include?('Unexpected response code')
|
|
96
|
-
log "If this is a Jetstream server, retry with -j / --jetstream."
|
|
138
|
+
log "If this is a Jetstream server, retry with -j / --jetstream.", true
|
|
97
139
|
end
|
|
98
140
|
end
|
|
99
141
|
|
|
@@ -107,13 +149,15 @@ module RatProto
|
|
|
107
149
|
end
|
|
108
150
|
|
|
109
151
|
def print_commit_message(msg)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
time = msg.time.getlocal.iso8601
|
|
152
|
+
time = msg.time.getlocal
|
|
113
153
|
@last_timestamp = time
|
|
114
154
|
|
|
155
|
+
return if @no_collections
|
|
156
|
+
return if @dids && !@dids.include?(msg.repo)
|
|
157
|
+
|
|
115
158
|
msg.operations.each do |op|
|
|
116
159
|
next if @collections && !@collections.include?(op.collection)
|
|
160
|
+
next if @operations && !@operations.include?(op.action)
|
|
117
161
|
|
|
118
162
|
json = op.raw_record && JSON.generate(op.raw_record.except('$type'))
|
|
119
163
|
puts "[#{time}] (#{msg.seq}) #{msg.repo} #{op.action.inspect} #{op.collection} #{op.rkey} #{json}"
|
|
@@ -121,11 +165,11 @@ module RatProto
|
|
|
121
165
|
end
|
|
122
166
|
|
|
123
167
|
def print_account_message(msg)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
time = msg.time.getlocal.iso8601
|
|
168
|
+
time = msg.time.getlocal
|
|
127
169
|
@last_timestamp = time
|
|
128
170
|
|
|
171
|
+
return if @dids && !@dids.include?(msg.repo)
|
|
172
|
+
|
|
129
173
|
status = (msg.active?) ? :active : msg.status
|
|
130
174
|
|
|
131
175
|
puts "[#{time}] (#{msg.seq}) #{msg.repo} #account (status = #{status.inspect})"
|
|
@@ -133,8 +177,8 @@ module RatProto
|
|
|
133
177
|
|
|
134
178
|
def show_account_messages?
|
|
135
179
|
if account? == nil
|
|
136
|
-
# enabled by default if -c is not used
|
|
137
|
-
@collections.nil?
|
|
180
|
+
# enabled by default if -c or -o is not used, or if commits were explicitly disabled
|
|
181
|
+
@no_collections || (@collections.nil? && @operations.nil?)
|
|
138
182
|
else
|
|
139
183
|
# if enabled/disabled explicitly, follow user's choice
|
|
140
184
|
account?
|
|
@@ -143,16 +187,21 @@ module RatProto
|
|
|
143
187
|
|
|
144
188
|
def configure_interrupt_handler
|
|
145
189
|
trap('SIGINT') do
|
|
146
|
-
log
|
|
190
|
+
log nil, true
|
|
147
191
|
log 'Disconnecting...'
|
|
148
192
|
@sky.disconnect
|
|
149
193
|
end
|
|
150
194
|
end
|
|
151
195
|
|
|
196
|
+
def log(text = nil, force = false)
|
|
197
|
+
super(text) unless quiet? && !force
|
|
198
|
+
end
|
|
199
|
+
|
|
152
200
|
def print_cursor_and_stop(msg)
|
|
153
201
|
return if @disconnecting
|
|
154
202
|
|
|
155
|
-
puts msg.seq
|
|
203
|
+
puts (print_time?) ? msg.time.getlocal : msg.seq
|
|
204
|
+
|
|
156
205
|
@sky.disconnect
|
|
157
206
|
@disconnecting = true
|
|
158
207
|
end
|
|
@@ -24,7 +24,9 @@ module RatProto
|
|
|
24
24
|
option ['-t', '--target'], 'PATTERN', "filter by labelled DID/URI (can be a pattern with '*' as a wildcard; repeatable)",
|
|
25
25
|
multivalued: true, attribute_name: :target_patterns
|
|
26
26
|
|
|
27
|
-
option ['-
|
|
27
|
+
option ['-q', '--quiet'], :flag, 'disable status messages'
|
|
28
|
+
option ['-s', '--print-cursor'], :flag, 'only print cursor (seq) of first event and disconnect'
|
|
29
|
+
option ['--print-time'], :flag, 'only print timestamp of first event and disconnect'
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def execute
|
|
@@ -37,12 +39,13 @@ module RatProto
|
|
|
37
39
|
@sky = Skyfall::Firehose.new(@service, :subscribe_labels, cursor)
|
|
38
40
|
configure_interrupt_handler
|
|
39
41
|
|
|
40
|
-
if print_cursor?
|
|
42
|
+
if print_cursor? || print_time?
|
|
41
43
|
@sky.on_message do |msg|
|
|
42
44
|
print_cursor_and_stop(msg)
|
|
43
45
|
next
|
|
44
46
|
end
|
|
45
47
|
|
|
48
|
+
@sky.on_error { |e| log "ERROR: #{e.message}" }
|
|
46
49
|
@sky.connect
|
|
47
50
|
else
|
|
48
51
|
configure_callbacks
|
|
@@ -90,35 +93,41 @@ module RatProto
|
|
|
90
93
|
@sky.on_disconnect { log "Disconnected" }
|
|
91
94
|
@sky.on_reconnect { log "Connection lost, trying to reconnect..." }
|
|
92
95
|
@sky.on_timeout { log "Connection stalled, triggering a reconnect..." }
|
|
93
|
-
@sky.on_error { |e| log "ERROR: #{e}" }
|
|
96
|
+
@sky.on_error { |e| log "ERROR: #{e.message}" }
|
|
94
97
|
|
|
95
98
|
@sky.on_message do |msg|
|
|
96
99
|
next unless msg.type == :labels
|
|
97
100
|
|
|
98
101
|
msg.labels.each do |label|
|
|
102
|
+
time = label.created_at.getlocal
|
|
103
|
+
@last_timestamp = time
|
|
104
|
+
|
|
99
105
|
next if @labels && !@labels.include?(label.value)
|
|
100
106
|
next if @targets && @targets.none? { |pattern| pattern.match?(label.subject) }
|
|
101
107
|
|
|
102
|
-
@last_timestamp = label.created_at
|
|
103
|
-
|
|
104
108
|
json = JSON.generate(label.data.except('cid', 'cts', 'sig', 'src', 'ver'))
|
|
105
|
-
puts "[#{
|
|
109
|
+
puts "[#{time}] (#{msg.seq}) #{json}"
|
|
106
110
|
end
|
|
107
111
|
end
|
|
108
112
|
end
|
|
109
113
|
|
|
110
114
|
def configure_interrupt_handler
|
|
111
115
|
trap('SIGINT') do
|
|
112
|
-
log
|
|
116
|
+
log nil, true
|
|
113
117
|
log 'Disconnecting...'
|
|
114
118
|
@sky.disconnect
|
|
115
119
|
end
|
|
116
120
|
end
|
|
117
121
|
|
|
122
|
+
def log(text = nil, force = false)
|
|
123
|
+
super(text) unless quiet? && !force
|
|
124
|
+
end
|
|
125
|
+
|
|
118
126
|
def print_cursor_and_stop(msg)
|
|
119
127
|
return if @disconnecting
|
|
120
128
|
|
|
121
|
-
puts msg.seq
|
|
129
|
+
puts (print_time?) ? msg.labels.first.created_at.getlocal : msg.seq
|
|
130
|
+
|
|
122
131
|
@sky.disconnect
|
|
123
132
|
@disconnecting = true
|
|
124
133
|
end
|
data/lib/ratproto/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ratproto
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kuba Suder
|
|
@@ -102,6 +102,7 @@ files:
|
|
|
102
102
|
- exe/rat
|
|
103
103
|
- lib/ratproto.rb
|
|
104
104
|
- lib/ratproto/cli.rb
|
|
105
|
+
- lib/ratproto/commands/account_status.rb
|
|
105
106
|
- lib/ratproto/commands/base.rb
|
|
106
107
|
- lib/ratproto/commands/fetch.rb
|
|
107
108
|
- lib/ratproto/commands/resolve.rb
|
|
@@ -117,6 +118,7 @@ metadata:
|
|
|
117
118
|
bug_tracker_uri: https://tangled.org/mackuba.eu/ratproto/issues
|
|
118
119
|
changelog_uri: https://tangled.org/mackuba.eu/ratproto/blob/master/CHANGELOG.md
|
|
119
120
|
source_code_uri: https://tangled.org/mackuba.eu/ratproto
|
|
121
|
+
rubygems_mfa_required: 'true'
|
|
120
122
|
rdoc_options: []
|
|
121
123
|
require_paths:
|
|
122
124
|
- lib
|