ratproto 0.3.2 → 0.3.4
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 +9 -0
- data/lib/ratproto/cli.rb +2 -0
- data/lib/ratproto/commands/account_status.rb +45 -0
- data/lib/ratproto/commands/stream.rb +38 -16
- data/lib/ratproto/commands/stream_labels.rb +11 -7
- data/lib/ratproto/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c5fee431ed4b84e739b1ff36768bfb1db007dd1457d63dfd1ba5279c92b66c00
|
|
4
|
+
data.tar.gz: 260c01a4b45629e2c55026404ad5bbbc6fe9e93a22647cba85d4897b11a7ed81
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ff763fe7c82d4a645de4228bf909e362b33efd98094390451bcf99b6b64c9ce165f83f17c4325746f7f4c73a076d3824944b5422c871f6bf25fdc89331f1a7a3
|
|
7
|
+
data.tar.gz: 855c076aa6553f04635f5275e2b94bef28bd78d91f816b9446cad9f8c5d305719dcb4dbdc85c986d9b736d3355d3cc4d2faec59425c2eca9f93b821c7cbf906e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## [0.3.4] - 2026-09-03
|
|
2
|
+
|
|
3
|
+
- `stream`: for Jetstream sources, you can pass e.g. '-4h' as the cursor to start from 4 hours ago
|
|
4
|
+
|
|
5
|
+
## [0.3.3] - 2026-08-17
|
|
6
|
+
|
|
7
|
+
- `stream`: added `--print-time` mode, bug fixes, unified timestamp formats
|
|
8
|
+
- added `status` command that prints account status
|
|
9
|
+
|
|
1
10
|
## [0.3.2] - 2026-07-30
|
|
2
11
|
|
|
3
12
|
- `stream`: filter by record operation type using `-o`
|
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
|
|
@@ -17,13 +17,8 @@ module RatProto
|
|
|
17
17
|
|
|
18
18
|
option ['-j', '--jetstream'], :flag, 'use a Jetstream source'
|
|
19
19
|
|
|
20
|
-
option
|
|
21
|
-
['-r', '--cursor'], 'CURSOR',
|
|
20
|
+
option ['-r', '--cursor'], 'CURSOR',
|
|
22
21
|
'start from a given cursor (pass 0 to read from the beginning of the playback window)'
|
|
23
|
-
) do |value|
|
|
24
|
-
raise ArgumentError, 'must be a decimal integer' unless value =~ /\A\d+\z/
|
|
25
|
-
value.to_i
|
|
26
|
-
end
|
|
27
22
|
|
|
28
23
|
option ['-d', '--did'], 'DID[,DID...]', 'filter events by DID (comma-separated or repeated)',
|
|
29
24
|
multivalued: true, attribute_name: :did_values
|
|
@@ -40,23 +35,26 @@ module RatProto
|
|
|
40
35
|
'print account status events (default: enabled unless filtering by collection or operation)'
|
|
41
36
|
|
|
42
37
|
option ['-q', '--quiet'], :flag, 'disable status messages'
|
|
43
|
-
option ['-s', '--print-cursor'], :flag, 'only print
|
|
38
|
+
option ['-s', '--print-cursor'], :flag, 'only print cursor (seq) of first event and disconnect'
|
|
39
|
+
option ['--print-time'], :flag, 'only print timestamp of first event and disconnect'
|
|
44
40
|
|
|
45
41
|
|
|
46
42
|
def execute
|
|
47
43
|
require 'skyfall'
|
|
48
44
|
|
|
49
45
|
prepare_filters
|
|
46
|
+
validate_cursor
|
|
50
47
|
|
|
51
48
|
@sky = build_stream
|
|
52
49
|
configure_interrupt_handler
|
|
53
50
|
|
|
54
|
-
if print_cursor?
|
|
51
|
+
if print_cursor? || print_time?
|
|
55
52
|
@sky.on_message do |msg|
|
|
56
53
|
print_cursor_and_stop(msg)
|
|
57
54
|
next
|
|
58
55
|
end
|
|
59
56
|
|
|
57
|
+
@sky.on_error { |e| report_error(e) }
|
|
60
58
|
@sky.connect
|
|
61
59
|
else
|
|
62
60
|
configure_callbacks
|
|
@@ -95,6 +93,29 @@ module RatProto
|
|
|
95
93
|
@operations = (@operations.length > 0) ? @operations.map { |operation| validate_operation(operation) } : nil
|
|
96
94
|
end
|
|
97
95
|
|
|
96
|
+
def validate_cursor
|
|
97
|
+
return if cursor.nil?
|
|
98
|
+
|
|
99
|
+
if cursor.start_with?('-')
|
|
100
|
+
if !jetstream?
|
|
101
|
+
signal_usage_error("time offset cursors are only supported with Jetstream right now")
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
if cursor =~ /\A\-([0-9]+(\.[0-9]+)?)([hms])\z/i
|
|
105
|
+
amount, unit = $1, $3.downcase
|
|
106
|
+
|
|
107
|
+
multiplier = { 'h' => 3600, 'm' => 60, 's' => 1 }[unit]
|
|
108
|
+
@cursor = (Time.now.to_f - amount.to_f * multiplier) * 1_000_000
|
|
109
|
+
else
|
|
110
|
+
signal_usage_error("invalid time offset specifier: #{cursor}")
|
|
111
|
+
end
|
|
112
|
+
elsif cursor =~ /\A[0-9]+\z/
|
|
113
|
+
@cursor = cursor.to_i
|
|
114
|
+
else
|
|
115
|
+
signal_usage_error("cursor must be an integer number or an offset specifier")
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
98
119
|
def validate_operation(operation)
|
|
99
120
|
if OPERATION_TYPES.include?(operation)
|
|
100
121
|
operation.to_sym
|
|
@@ -106,7 +127,7 @@ module RatProto
|
|
|
106
127
|
def build_stream
|
|
107
128
|
if jetstream?
|
|
108
129
|
options = {}
|
|
109
|
-
options[:cursor] = cursor if cursor
|
|
130
|
+
options[:cursor] = @cursor if @cursor
|
|
110
131
|
|
|
111
132
|
# pass DID/collection filters to Jetstream to filter events server-side
|
|
112
133
|
options[:wanted_dids] = @dids if @dids
|
|
@@ -147,12 +168,12 @@ module RatProto
|
|
|
147
168
|
end
|
|
148
169
|
|
|
149
170
|
def print_commit_message(msg)
|
|
171
|
+
time = msg.time.getlocal
|
|
172
|
+
@last_timestamp = time
|
|
173
|
+
|
|
150
174
|
return if @no_collections
|
|
151
175
|
return if @dids && !@dids.include?(msg.repo)
|
|
152
176
|
|
|
153
|
-
time = msg.time.getlocal.iso8601
|
|
154
|
-
@last_timestamp = time
|
|
155
|
-
|
|
156
177
|
msg.operations.each do |op|
|
|
157
178
|
next if @collections && !@collections.include?(op.collection)
|
|
158
179
|
next if @operations && !@operations.include?(op.action)
|
|
@@ -163,11 +184,11 @@ module RatProto
|
|
|
163
184
|
end
|
|
164
185
|
|
|
165
186
|
def print_account_message(msg)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
time = msg.time.getlocal.iso8601
|
|
187
|
+
time = msg.time.getlocal
|
|
169
188
|
@last_timestamp = time
|
|
170
189
|
|
|
190
|
+
return if @dids && !@dids.include?(msg.repo)
|
|
191
|
+
|
|
171
192
|
status = (msg.active?) ? :active : msg.status
|
|
172
193
|
|
|
173
194
|
puts "[#{time}] (#{msg.seq}) #{msg.repo} #account (status = #{status.inspect})"
|
|
@@ -198,7 +219,8 @@ module RatProto
|
|
|
198
219
|
def print_cursor_and_stop(msg)
|
|
199
220
|
return if @disconnecting
|
|
200
221
|
|
|
201
|
-
puts msg.seq
|
|
222
|
+
puts (print_time?) ? msg.time.getlocal : msg.seq
|
|
223
|
+
|
|
202
224
|
@sky.disconnect
|
|
203
225
|
@disconnecting = true
|
|
204
226
|
end
|
|
@@ -25,7 +25,8 @@ module RatProto
|
|
|
25
25
|
multivalued: true, attribute_name: :target_patterns
|
|
26
26
|
|
|
27
27
|
option ['-q', '--quiet'], :flag, 'disable status messages'
|
|
28
|
-
option ['-s', '--print-cursor'], :flag, 'only print
|
|
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'
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
def execute
|
|
@@ -38,12 +39,13 @@ module RatProto
|
|
|
38
39
|
@sky = Skyfall::Firehose.new(@service, :subscribe_labels, cursor)
|
|
39
40
|
configure_interrupt_handler
|
|
40
41
|
|
|
41
|
-
if print_cursor?
|
|
42
|
+
if print_cursor? || print_time?
|
|
42
43
|
@sky.on_message do |msg|
|
|
43
44
|
print_cursor_and_stop(msg)
|
|
44
45
|
next
|
|
45
46
|
end
|
|
46
47
|
|
|
48
|
+
@sky.on_error { |e| log "ERROR: #{e.message}" }
|
|
47
49
|
@sky.connect
|
|
48
50
|
else
|
|
49
51
|
configure_callbacks
|
|
@@ -91,19 +93,20 @@ module RatProto
|
|
|
91
93
|
@sky.on_disconnect { log "Disconnected" }
|
|
92
94
|
@sky.on_reconnect { log "Connection lost, trying to reconnect..." }
|
|
93
95
|
@sky.on_timeout { log "Connection stalled, triggering a reconnect..." }
|
|
94
|
-
@sky.on_error { |e| log "ERROR: #{e}" }
|
|
96
|
+
@sky.on_error { |e| log "ERROR: #{e.message}" }
|
|
95
97
|
|
|
96
98
|
@sky.on_message do |msg|
|
|
97
99
|
next unless msg.type == :labels
|
|
98
100
|
|
|
99
101
|
msg.labels.each do |label|
|
|
102
|
+
time = label.created_at.getlocal
|
|
103
|
+
@last_timestamp = time
|
|
104
|
+
|
|
100
105
|
next if @labels && !@labels.include?(label.value)
|
|
101
106
|
next if @targets && @targets.none? { |pattern| pattern.match?(label.subject) }
|
|
102
107
|
|
|
103
|
-
@last_timestamp = label.created_at
|
|
104
|
-
|
|
105
108
|
json = JSON.generate(label.data.except('cid', 'cts', 'sig', 'src', 'ver'))
|
|
106
|
-
puts "[#{
|
|
109
|
+
puts "[#{time}] (#{msg.seq}) #{json}"
|
|
107
110
|
end
|
|
108
111
|
end
|
|
109
112
|
end
|
|
@@ -123,7 +126,8 @@ module RatProto
|
|
|
123
126
|
def print_cursor_and_stop(msg)
|
|
124
127
|
return if @disconnecting
|
|
125
128
|
|
|
126
|
-
puts msg.seq
|
|
129
|
+
puts (print_time?) ? msg.labels.first.created_at.getlocal : msg.seq
|
|
130
|
+
|
|
127
131
|
@sky.disconnect
|
|
128
132
|
@disconnecting = true
|
|
129
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.4
|
|
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
|
|
@@ -131,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
131
133
|
- !ruby/object:Gem::Version
|
|
132
134
|
version: '0'
|
|
133
135
|
requirements: []
|
|
134
|
-
rubygems_version:
|
|
136
|
+
rubygems_version: 4.0.18
|
|
135
137
|
specification_version: 4
|
|
136
138
|
summary: Ruby CLI tool for accessing Bluesky API / ATProto
|
|
137
139
|
test_files: []
|