bskyrb 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/bskyrb/codegen.rb +211 -0
- data/lib/bskyrb/firehose.rb +39 -0
- data/lib/bskyrb/generated_classes.rb +5430 -0
- data/lib/bskyrb/records.rb +231 -0
- data/lib/bskyrb/session.rb +116 -0
- data/lib/bskyrb/version.rb +5 -0
- data/lib/bskyrb.rb +5 -0
- metadata +12 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0446dc11827c6a05fef76c05c2e6a8352c0d22aca38596b38829a992905f3724
|
4
|
+
data.tar.gz: bb1388b216c99ec84219439b087b74f43d39bb27bc7b6a8bb40c2cc73791c11e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0c77673776705697470560d6142ba51f0f88d0cfd81d536af44cba856bd82ad271c9a7ab5446af463dd1f930e1f54b0a49354bd9f8fae208a8df65a71b2adb3
|
7
|
+
data.tar.gz: 38939c101cc5f0eee20f9ddf52ef1da5ded8bef79654ef7a6f04f45f311c7771c27322e2c2137869c2202f3899ba22fc52ec64e0524d896821394e2e34dd102d
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require "json"
|
2
|
+
require "erb"
|
3
|
+
|
4
|
+
module Bskyrb
|
5
|
+
module LexiconParser
|
6
|
+
@@active_namespace = ""
|
7
|
+
|
8
|
+
def self.def_is_query(defn)
|
9
|
+
defn["defs"].has_key?("main") &&
|
10
|
+
defn["defs"]["main"].has_key?("type") &&
|
11
|
+
defn["defs"]["main"]["type"] == "query"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.def_is_subscription(defn)
|
15
|
+
defn["defs"].has_key?("main") &&
|
16
|
+
defn["defs"]["main"].has_key?("type") &&
|
17
|
+
defn["defs"]["main"]["type"] == "subscription"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.def_is_procedure(defn)
|
21
|
+
defn["defs"].has_key?("main") &&
|
22
|
+
defn["defs"]["main"].has_key?("type") &&
|
23
|
+
defn["defs"]["main"]["type"] == "procedure"
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.build_classes_hash_from_lexicon_defs(lexicon_file)
|
27
|
+
parsed = File.open(lexicon_file) { |f| JSON.parse(f.read) }
|
28
|
+
output = {}
|
29
|
+
# return if def_is_query(parsed) || def_is_procedure(parsed) || def_is_subscription(parsed)
|
30
|
+
parsed["defs"].each do |k, v| # map {|v| build_class_hash_from_schema(v)}
|
31
|
+
next if v["type"] == "main" # skip queries, procedures, etc.
|
32
|
+
@@active_namespace = parsed["id"].split(".").map(&:capitalize).join("")
|
33
|
+
next if k == "main"
|
34
|
+
output[ref_to_class_str(k)] = if v["type"] == "record"
|
35
|
+
build_class_hash_from_schema(v["record"]["properties"])
|
36
|
+
else
|
37
|
+
build_class_hash_from_schema(v)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
output
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.build_queries_and_procedures_from_lexicon(lexicon_file)
|
44
|
+
parsed = File.open(lexicon_file) { |f| JSON.parse(f.read) }
|
45
|
+
output = {}
|
46
|
+
return unless def_is_query(parsed) || def_is_procedure(parsed)
|
47
|
+
parsed["defs"].each do |k, v| # map {|v| build_class_hash_from_schema(v)}
|
48
|
+
next if k != "main" || v["type"] == "record" # skip basic defs
|
49
|
+
next if v["type"] == "subscription" # some day
|
50
|
+
@@active_namespace = parsed["id"].split(".").map(&:capitalize).join("")
|
51
|
+
class_name = ref_to_class_str(parsed["id"].split(".").last)
|
52
|
+
built_def = {}
|
53
|
+
output[class_name] = {}
|
54
|
+
if v["type"] == "query"
|
55
|
+
built_def["input"] = build_class_hash_from_schema(v["parameters"])
|
56
|
+
if v["output"] && v["output"]["schema"]
|
57
|
+
built_def["output"] = build_class_hash_from_schema(v["output"]["schema"])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
if v["type"] == "procedure"
|
61
|
+
if v["input"]
|
62
|
+
built_def["input"] = build_class_hash_from_schema(v["input"]["schema"])
|
63
|
+
end
|
64
|
+
if v["output"] && v["output"]["schema"]
|
65
|
+
built_def["output"] = build_class_hash_from_schema(v["output"]["schema"])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
output[class_name] = built_def unless built_def.empty?
|
69
|
+
end
|
70
|
+
output
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.build_class_hash_from_schema(json_schema, output = {})
|
74
|
+
return if json_schema.nil?
|
75
|
+
return if json_schema.has_key? "main"
|
76
|
+
to_process = json_schema["properties"] || json_schema
|
77
|
+
to_process.each_pair do |key, value|
|
78
|
+
if key == "type" || !value.is_a?(Hash) # || value["type"] == "query" || key == "main"
|
79
|
+
next
|
80
|
+
end
|
81
|
+
|
82
|
+
output[key] = if value["type"] == "object"
|
83
|
+
build_class_hash_from_schema(value, {})
|
84
|
+
elsif value["type"] == "array"
|
85
|
+
[build_class_hash_from_schema(value, {}).values.first]
|
86
|
+
elsif value["type"] == "ref"
|
87
|
+
ref_to_class_str(value["ref"])
|
88
|
+
else
|
89
|
+
-1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
output
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.ref_to_class_str(ref, ns = @@active_namespace)
|
96
|
+
klass_str_lower = ref.split("#")[-1]
|
97
|
+
klass_str = klass_str_lower[0].capitalize + klass_str_lower.slice(1..)
|
98
|
+
ns += "::" if ns
|
99
|
+
"#{ns}#{klass_str}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.basic_template
|
103
|
+
%(
|
104
|
+
module <%= klass_str.split("::").first %>
|
105
|
+
class <%= klass_str.split("::").last %>
|
106
|
+
<% properties.each do |key, value| %>
|
107
|
+
attr_accessor :<%= key %>
|
108
|
+
<% end %>
|
109
|
+
|
110
|
+
def self.from_hash(hash)
|
111
|
+
# httparty-returned string-keyed hash
|
112
|
+
instance = new
|
113
|
+
<% properties.each do |key, value| %>
|
114
|
+
instance.send("<%= key %>=", hash["<%= key %>"])
|
115
|
+
<% end %>
|
116
|
+
instance
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.basic_class_definitions(classes_hash)
|
124
|
+
classes_hash.map do |klass_str, properties|
|
125
|
+
ERB.new(basic_template).result_with_hash({klass_str: klass_str, properties: properties})
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.input_output_template
|
130
|
+
%(
|
131
|
+
module <%= klass_str.split("::").first %>
|
132
|
+
module <%= klass_str.split("::").last %>
|
133
|
+
<% ["input", "output"].each do |top_level_key| %>
|
134
|
+
<% next unless properties.has_key?(top_level_key) && !properties[top_level_key].nil? %>
|
135
|
+
class <%= top_level_key.capitalize %>
|
136
|
+
<% properties[top_level_key].each do |key, value| %>
|
137
|
+
attr_accessor :<%= key %>
|
138
|
+
<% end %>
|
139
|
+
|
140
|
+
def self.from_hash(hash)
|
141
|
+
# httparty-returned string-keyed hash
|
142
|
+
instance = new
|
143
|
+
<% properties[top_level_key].each do |key, value| %>
|
144
|
+
instance.send("<%= key %>=", hash["<%= key %>"])
|
145
|
+
<% end %>
|
146
|
+
instance
|
147
|
+
end
|
148
|
+
|
149
|
+
def to_h
|
150
|
+
{
|
151
|
+
<% properties[top_level_key].each do |key, value| %>
|
152
|
+
"<%= key %>" => <%= key %>,
|
153
|
+
<% end %>
|
154
|
+
}
|
155
|
+
end
|
156
|
+
end
|
157
|
+
<% end %>
|
158
|
+
end
|
159
|
+
end
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.input_output_class_definitions(classes_hash)
|
164
|
+
classes_hash.map do |klass_str, properties|
|
165
|
+
ERB.new(input_output_template).result_with_hash({klass_str: klass_str, properties: properties})
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class DynamicClassFromHash
|
171
|
+
def self.from_hash(hash)
|
172
|
+
hash.each do |klass_sym, properties|
|
173
|
+
Object.const_set(klass_sym, Class.new do
|
174
|
+
attr_accessor(*properties.keys.map(&:to_sym))
|
175
|
+
|
176
|
+
def self.from_hash(properties)
|
177
|
+
# httparty-returned string-keyed hash body
|
178
|
+
instance = new
|
179
|
+
properties.each do |key, value|
|
180
|
+
instance.send("#{key}=", value)
|
181
|
+
end
|
182
|
+
instance
|
183
|
+
end
|
184
|
+
end)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
if __FILE__ == $0
|
191
|
+
basic_defs = {}
|
192
|
+
Dir["atproto/lexicons/**/*.json"].each do |file|
|
193
|
+
hashes = Bskyrb::LexiconParser.build_classes_hash_from_lexicon_defs(file)
|
194
|
+
basic_defs = basic_defs.merge(hashes) unless hashes.empty?
|
195
|
+
end
|
196
|
+
|
197
|
+
input_output_defs = {}
|
198
|
+
Dir["atproto/lexicons/**/*.json"].each do |file|
|
199
|
+
hashes = Bskyrb::LexiconParser.build_queries_and_procedures_from_lexicon(file)
|
200
|
+
input_output_defs = input_output_defs.merge(hashes) unless hashes.nil? || hashes.empty?
|
201
|
+
end
|
202
|
+
|
203
|
+
File.open("lib/bskyrb/generated_classes.rb", "w") do |f|
|
204
|
+
f.puts "module Bskyrb"
|
205
|
+
f.puts Bskyrb::LexiconParser.basic_class_definitions(basic_defs)
|
206
|
+
f.puts Bskyrb::LexiconParser.input_output_class_definitions(input_output_defs)
|
207
|
+
f.puts "end"
|
208
|
+
end
|
209
|
+
`bin/format`
|
210
|
+
`bundle exec rbs prototype rb lib/bskyrb/generated_classes.rb > sig/generated_classes.rbs`
|
211
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'faye/websocket'
|
2
|
+
require 'eventmachine'
|
3
|
+
require 'cbor'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
EM.run {
|
7
|
+
ws = Faye::WebSocket::Client.new('wss://bsky.social/xrpc/com.atproto.sync.subscribeRepos')
|
8
|
+
|
9
|
+
ws.on :open do |event|
|
10
|
+
p [:open]
|
11
|
+
ws.send('Hello, world!')
|
12
|
+
end
|
13
|
+
|
14
|
+
ws.on :message do |event|
|
15
|
+
msg_bytes = event.data
|
16
|
+
unpacker = CBOR::Unpacker.new(StringIO.new(msg_bytes.pack('C*')))
|
17
|
+
header, payload = unpacker.each.to_a
|
18
|
+
|
19
|
+
# decoder = CBOR::Decoding.new(StringIO.new(msg_bytes.pack('C*')))
|
20
|
+
# while item = decoder.read
|
21
|
+
# puts item
|
22
|
+
# end
|
23
|
+
|
24
|
+
begin
|
25
|
+
if payload["ops"].first["path"].include? "app.bsky.feed.post"
|
26
|
+
#payload#["blocks"].length
|
27
|
+
decoded = CBOR.decode(payload)
|
28
|
+
|
29
|
+
# Convert the decoded object to JSON
|
30
|
+
json = decoded.to_json
|
31
|
+
|
32
|
+
# Print the JSON object
|
33
|
+
puts json
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
}
|
39
|
+
# end
|