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