async-matrix 2.1.0-arm-linux → 3.0.0-arm-linux
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/README.md +33 -58
- data/lib/async/matrix/3.3/async_matrix_e2ee.so +0 -0
- data/lib/async/matrix/3.4/async_matrix_e2ee.so +0 -0
- data/lib/async/matrix/4.0/async_matrix_e2ee.so +0 -0
- data/lib/async/matrix/api/chain.rb +120 -94
- data/lib/async/matrix/api/concat.rb +28 -22
- data/lib/async/matrix/api/path_tree.rb +71 -44
- data/lib/async/matrix/api.rb +6 -1
- data/lib/async/matrix/auth_error.rb +20 -0
- data/lib/async/matrix/bad_json_error.rb +20 -0
- data/lib/async/matrix/client.rb +142 -110
- data/lib/async/matrix/config/vivify.rb +107 -0
- data/lib/async/matrix/config.rb +184 -0
- data/lib/async/matrix/content.rb +106 -0
- data/lib/async/matrix/double_puppet_client.rb +1 -1
- data/lib/async/matrix/error.rb +0 -27
- data/lib/async/matrix/{application_service/error_response.rb → error_response.rb} +10 -10
- data/lib/async/matrix/event.rb +197 -0
- data/lib/async/matrix/homeserver_error.rb +20 -0
- data/lib/async/matrix/invalid_endpoint_error.rb +20 -0
- data/lib/async/matrix/media_client.rb +46 -35
- data/lib/async/matrix/not_found_error.rb +20 -0
- data/lib/async/matrix/notifier.rb +7 -3
- data/lib/async/matrix/response_too_large_error.rb +20 -0
- data/lib/async/matrix/schema/registry.rb +367 -340
- data/lib/async/matrix/schema/validation_error.rb +221 -214
- data/lib/async/matrix/schema.rb +161 -161
- data/lib/async/matrix/version.rb +3 -3
- data/lib/async/matrix.rb +0 -7
- metadata +25 -133
- data/lib/async/discord/api/path_tree.rb +0 -127
- data/lib/async/discord/api.rb +0 -151
- data/lib/async/discord/client.rb +0 -283
- data/lib/async/discord/error.rb +0 -84
- data/lib/async/discord/gateway.rb +0 -359
- data/lib/async/discord.rb +0 -15
- data/lib/async/matrix/application_service/bot.rb +0 -232
- data/lib/async/matrix/application_service/config/schema/analytics.json +0 -21
- data/lib/async/matrix/application_service/config/schema/appservice.json +0 -82
- data/lib/async/matrix/application_service/config/schema/backfill.json +0 -91
- data/lib/async/matrix/application_service/config/schema/bridge.json +0 -209
- data/lib/async/matrix/application_service/config/schema/config.json +0 -61
- data/lib/async/matrix/application_service/config/schema/database.json +0 -38
- data/lib/async/matrix/application_service/config/schema/direct_media.json +0 -35
- data/lib/async/matrix/application_service/config/schema/double_puppet.json +0 -24
- data/lib/async/matrix/application_service/config/schema/encryption.json +0 -164
- data/lib/async/matrix/application_service/config/schema/homeserver.json +0 -58
- data/lib/async/matrix/application_service/config/schema/logging.json +0 -50
- data/lib/async/matrix/application_service/config/schema/management_room_texts.json +0 -25
- data/lib/async/matrix/application_service/config/schema/matrix.json +0 -45
- data/lib/async/matrix/application_service/config/schema/permissions.json +0 -54
- data/lib/async/matrix/application_service/config/schema/provisioning.json +0 -23
- data/lib/async/matrix/application_service/config/schema/public_media.json +0 -39
- data/lib/async/matrix/application_service/config/schema/relay.json +0 -43
- data/lib/async/matrix/application_service/config/vivify.rb +0 -109
- data/lib/async/matrix/application_service/config.rb +0 -225
- data/lib/async/matrix/application_service/dispatcher.rb +0 -185
- data/lib/async/matrix/application_service/event.rb +0 -285
- data/lib/async/matrix/application_service/server.rb +0 -430
- data/lib/async/matrix/application_service/transaction.rb +0 -66
- data/lib/async/matrix/application_service/transaction_handler.rb +0 -185
- data/lib/async/matrix/application_service/transaction_store.rb +0 -80
- data/lib/async/matrix/bridge/discord/db/connection.rb +0 -141
- data/lib/async/matrix/bridge/discord/db/file.rb +0 -118
- data/lib/async/matrix/bridge/discord/db/guild.rb +0 -120
- data/lib/async/matrix/bridge/discord/db/message.rb +0 -160
- data/lib/async/matrix/bridge/discord/db/migrations/001_create_users.rb +0 -14
- data/lib/async/matrix/bridge/discord/db/migrations/002_create_guilds.rb +0 -14
- data/lib/async/matrix/bridge/discord/db/migrations/003_create_portals.rb +0 -23
- data/lib/async/matrix/bridge/discord/db/migrations/004_create_puppets.rb +0 -19
- data/lib/async/matrix/bridge/discord/db/migrations/005_create_messages.rb +0 -20
- data/lib/async/matrix/bridge/discord/db/migrations/006_create_reactions.rb +0 -19
- data/lib/async/matrix/bridge/discord/db/migrations/007_create_files.rb +0 -18
- data/lib/async/matrix/bridge/discord/db/portal.rb +0 -150
- data/lib/async/matrix/bridge/discord/db/puppet.rb +0 -128
- data/lib/async/matrix/bridge/discord/db/reaction.rb +0 -165
- data/lib/async/matrix/bridge/discord/db/schema.rb +0 -18
- data/lib/async/matrix/bridge/discord/db/user.rb +0 -112
- data/lib/async/matrix/bridge/discord/db.rb +0 -138
|
@@ -9,346 +9,373 @@ require "json_schemer"
|
|
|
9
9
|
require "pathname"
|
|
10
10
|
|
|
11
11
|
module Async
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
12
|
+
module Matrix
|
|
13
|
+
module Schema
|
|
14
|
+
# Loads and indexes Matrix event schemas from the official matrix-org/matrix-spec
|
|
15
|
+
# YAML files bundled in data/matrix-spec/event-schemas/schema/.
|
|
16
|
+
#
|
|
17
|
+
# Schemas are loaded lazily on first access and cached for the lifetime of the
|
|
18
|
+
# process. Each schema is a JSONSchemer::Schema instance that resolves relative
|
|
19
|
+
# $ref paths (e.g. core-event-schema/room_event.yaml) via a file-based resolver.
|
|
20
|
+
#
|
|
21
|
+
# registry = Async::Matrix::Schema::Registry.instance
|
|
22
|
+
# registry["m.room.message"] # => JSONSchemer::Schema
|
|
23
|
+
# registry.variant("m.room.message", "m.text") # => JSONSchemer::Schema
|
|
24
|
+
# registry.event_types # => ["m.accepted_terms", ...]
|
|
25
|
+
#
|
|
26
|
+
class Registry
|
|
27
|
+
# Custom format validators for Matrix-specific format hints.
|
|
28
|
+
MATRIX_FORMATS = {
|
|
29
|
+
"mx-user-id" => ->(value, _schema) { value.is_a?(String) && value.match?(/\A@[^:]+:.+\z/) },
|
|
30
|
+
"mx-room-id" => ->(value, _schema) { value.is_a?(String) && value.match?(/\A![^:]+:.+\z/) },
|
|
31
|
+
"mx-event-id" => ->(value, _schema) { value.is_a?(String) && value.match?(/\A\$/) },
|
|
32
|
+
"mx-room-alias" => ->(value, _schema) { value.is_a?(String) && value.match?(/\A#[^:]+:.+\z/) },
|
|
33
|
+
"mx-server-name" => ->(value, _schema) { value.is_a?(String) && !value.empty? },
|
|
34
|
+
"mx-unpadded-base64" => ->(value, _schema) { value.is_a?(String) && value.match?(/\A[A-Za-z0-9+\/]*\z/) },
|
|
35
|
+
}.freeze
|
|
36
|
+
|
|
37
|
+
GEM_ROOT = File.expand_path("../../../..", __dir__)
|
|
38
|
+
SCHEMA_DIR = File.join(
|
|
39
|
+
GEM_ROOT,
|
|
40
|
+
"data",
|
|
41
|
+
"matrix-spec",
|
|
42
|
+
"event-schemas",
|
|
43
|
+
"schema",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
@instance = nil
|
|
47
|
+
|
|
48
|
+
class << self
|
|
49
|
+
# Returns the singleton Registry instance, creating it on first access.
|
|
50
|
+
def instance
|
|
51
|
+
@instance ||= new
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Reset the singleton (useful for testing).
|
|
55
|
+
def reset!
|
|
56
|
+
@instance = nil
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def initialize
|
|
61
|
+
@schemas = {}
|
|
62
|
+
@variants = {}
|
|
63
|
+
@loaded = false
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Look up a schema by Matrix event type (e.g. "m.room.message").
|
|
67
|
+
# Returns a JSONSchemer::Schema or nil if no schema exists for that type.
|
|
68
|
+
def [](event_type)
|
|
69
|
+
unless @loaded
|
|
70
|
+
load_schemas!
|
|
71
|
+
end
|
|
72
|
+
@schemas[event_type]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Look up a variant schema (e.g. variant("m.room.message", "m.text")).
|
|
76
|
+
# Returns a JSONSchemer::Schema or nil.
|
|
77
|
+
def variant(event_type, subtype)
|
|
78
|
+
unless @loaded
|
|
79
|
+
load_schemas!
|
|
80
|
+
end
|
|
81
|
+
@variants[[event_type, subtype]]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# All known base event types (excludes variant subtypes).
|
|
85
|
+
# @return [Array<String>] sorted event type strings
|
|
86
|
+
def event_types
|
|
87
|
+
unless @loaded
|
|
88
|
+
load_schemas!
|
|
89
|
+
end
|
|
90
|
+
@schemas.keys.sort
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# All known variant keys as [event_type, subtype] pairs.
|
|
94
|
+
# @return [Array<Array(String, String)>]
|
|
95
|
+
def variant_types
|
|
96
|
+
unless @loaded
|
|
97
|
+
load_schemas!
|
|
98
|
+
end
|
|
99
|
+
@variants.keys.sort
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Total number of schemas loaded (base + variants).
|
|
103
|
+
def size
|
|
104
|
+
unless @loaded
|
|
105
|
+
load_schemas!
|
|
106
|
+
end
|
|
107
|
+
@schemas.size + @variants.size
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Validate an event hash against its schema.
|
|
111
|
+
# Returns an array of error hashes (empty if valid).
|
|
112
|
+
# If no schema exists for the event type, returns empty (lenient).
|
|
113
|
+
def validate(event_hash)
|
|
114
|
+
event_type = event_hash["type"]
|
|
115
|
+
if event_type
|
|
116
|
+
base = self[event_type]
|
|
117
|
+
if base
|
|
118
|
+
errors = base.validate(event_hash).to_a
|
|
119
|
+
variant_key = detect_variant_key(event_type, event_hash)
|
|
120
|
+
if variant_key
|
|
121
|
+
variant_schema = variant(event_type, variant_key)
|
|
122
|
+
if variant_schema
|
|
123
|
+
errors.concat(variant_schema.validate(event_hash).to_a)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
errors
|
|
127
|
+
else
|
|
128
|
+
[]
|
|
129
|
+
end
|
|
130
|
+
else
|
|
131
|
+
[]
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Boolean validation.
|
|
136
|
+
def valid?(event_hash)
|
|
137
|
+
validate(event_hash).empty?
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Content properties defined by the schema for a given event type.
|
|
141
|
+
# Returns an array of property name strings, or empty array if unknown.
|
|
142
|
+
def content_properties(event_type)
|
|
143
|
+
schema = self[event_type]
|
|
144
|
+
if schema
|
|
145
|
+
extract_content_properties(schema.value)
|
|
146
|
+
else
|
|
147
|
+
[]
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
private
|
|
152
|
+
|
|
153
|
+
# Ref resolver that loads YAML/JSON files from disk.
|
|
154
|
+
# json_schemer calls this with a URI for each $ref it encounters.
|
|
155
|
+
def ref_resolver
|
|
156
|
+
@ref_resolver ||= proc do |uri|
|
|
157
|
+
path = uri.path
|
|
158
|
+
if path && File.exist?(path)
|
|
159
|
+
content = File.read(path)
|
|
160
|
+
if path.end_with?(".yaml", ".yml")
|
|
161
|
+
YAML.safe_load(content, permitted_classes: [Symbol])
|
|
162
|
+
else
|
|
163
|
+
JSON.parse(content)
|
|
164
|
+
end
|
|
165
|
+
else
|
|
166
|
+
raise JSONSchemer::UnknownRef, uri.to_s
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Build a JSONSchemer::Schema from a parsed YAML hash, anchored at the
|
|
172
|
+
# given file path so relative $ref paths resolve correctly.
|
|
173
|
+
def build_schemer(parsed, file_path)
|
|
174
|
+
uri = URI("file://#{File.expand_path(file_path)}")
|
|
175
|
+
JSONSchemer.schema(
|
|
176
|
+
parsed,
|
|
177
|
+
base_uri: uri,
|
|
178
|
+
ref_resolver: ref_resolver,
|
|
179
|
+
insert_property_defaults: false,
|
|
180
|
+
formats: MATRIX_FORMATS,
|
|
181
|
+
)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Scan the schema directory and load all event schemas.
|
|
185
|
+
def load_schemas!
|
|
186
|
+
if @loaded
|
|
187
|
+
nil
|
|
188
|
+
else
|
|
189
|
+
Dir.glob(File.join(SCHEMA_DIR, "*.yaml")).each do |path|
|
|
190
|
+
load_schema_file(path)
|
|
191
|
+
end
|
|
192
|
+
Dir.glob(File.join(SCHEMA_DIR, "*.json")).each do |path|
|
|
193
|
+
load_schema_file(path)
|
|
194
|
+
end
|
|
195
|
+
@loaded = true
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def load_schema_file(path)
|
|
200
|
+
filename = File.basename(path, File.extname(path))
|
|
201
|
+
content = File.read(path)
|
|
202
|
+
if path.end_with?(".json")
|
|
203
|
+
parsed = JSON.parse(content)
|
|
204
|
+
else
|
|
205
|
+
parsed = YAML.safe_load(content, permitted_classes: [Symbol])
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
schemer = build_schemer(parsed, path)
|
|
209
|
+
|
|
210
|
+
# Detect event type from schema: properties.type.enum[0]
|
|
211
|
+
declared_type = parsed.dig("properties", "type", "enum")&.first
|
|
212
|
+
|
|
213
|
+
if filename.include?("$")
|
|
214
|
+
# Variant schema: "m.room.message$m.text" -> base="m.room.message", sub="m.text"
|
|
215
|
+
parts = filename.split("$", 2)
|
|
216
|
+
base_type = declared_type || parts[0]
|
|
217
|
+
subtype = parts[1]
|
|
218
|
+
@variants[[base_type, subtype]] = schemer
|
|
219
|
+
elsif declared_type
|
|
220
|
+
@schemas[declared_type] = schemer
|
|
221
|
+
else
|
|
222
|
+
# Schemas without a type enum (like core-event-schema/) are skipped
|
|
223
|
+
# from the index -- they're only used as $ref targets.
|
|
224
|
+
end
|
|
225
|
+
rescue => e
|
|
226
|
+
# Don't let a single broken schema prevent loading the rest
|
|
227
|
+
warn "async-matrix: failed to load schema #{path}: #{e.message}"
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Detect the variant subtype key from an event hash.
|
|
231
|
+
# For m.room.message, the variant is the msgtype.
|
|
232
|
+
# For m.room.encrypted, the variant is the algorithm.
|
|
233
|
+
# For m.key.verification.start, the variant is the method.
|
|
234
|
+
def detect_variant_key(event_type, event_hash)
|
|
235
|
+
content = event_hash["content"]
|
|
236
|
+
if content.is_a?(Hash)
|
|
237
|
+
case event_type
|
|
238
|
+
when "m.room.message"
|
|
239
|
+
content["msgtype"]
|
|
240
|
+
when "m.room.encrypted"
|
|
241
|
+
content["algorithm"]
|
|
242
|
+
when "m.key.verification.start"
|
|
243
|
+
content["method"]
|
|
244
|
+
end
|
|
245
|
+
else
|
|
246
|
+
nil
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Extract content property names from a schema's parsed YAML.
|
|
251
|
+
def extract_content_properties(schema_hash)
|
|
252
|
+
props = schema_hash.dig("properties", "content", "properties")
|
|
253
|
+
if props.is_a?(Hash)
|
|
254
|
+
props.keys
|
|
255
|
+
else
|
|
256
|
+
[]
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
235
262
|
end
|
|
236
263
|
|
|
237
264
|
__END__
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
265
|
+
describe "Async::Matrix::Schema::Registry" do
|
|
266
|
+
it "loads schemas from disk" do
|
|
267
|
+
Async::Matrix::Schema::Registry.instance.size.should.be > 0
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it "has known event types" do
|
|
271
|
+
types = Async::Matrix::Schema::Registry.instance.event_types
|
|
272
|
+
types.should.include "m.room.message"
|
|
273
|
+
types.should.include "m.room.member"
|
|
274
|
+
types.should.include "m.room.create"
|
|
275
|
+
types.should.include "m.reaction"
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it "returns a JSONSchemer::Schema for a known type" do
|
|
279
|
+
schema = Async::Matrix::Schema::Registry.instance["m.room.message"]
|
|
280
|
+
schema.should.not.be.nil
|
|
281
|
+
schema.should.be.kind_of JSONSchemer::Schema
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
it "returns nil for an unknown type" do
|
|
285
|
+
Async::Matrix::Schema::Registry.instance["m.fake.event"].should.be.nil
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
it "has variant schemas" do
|
|
289
|
+
Async::Matrix::Schema::Registry.instance.variant_types.should.not.be.empty
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
it "resolves variant schemas" do
|
|
293
|
+
schema = Async::Matrix::Schema::Registry.instance.variant("m.room.message", "m.text")
|
|
294
|
+
schema.should.not.be.nil
|
|
295
|
+
schema.should.be.kind_of JSONSchemer::Schema
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
it "validates a correct m.room.message event" do
|
|
299
|
+
event = {
|
|
300
|
+
"type" => "m.room.message",
|
|
301
|
+
"content" => {"msgtype" => "m.text", "body" => "hello"},
|
|
302
|
+
"event_id" => "$abc123",
|
|
303
|
+
"sender" => "@alice:example.org",
|
|
304
|
+
"origin_server_ts" => 1234567890,
|
|
305
|
+
"room_id" => "!room:example.org"
|
|
306
|
+
}
|
|
307
|
+
Async::Matrix::Schema::Registry.instance.valid?(event).should == true
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
it "rejects m.room.message missing body" do
|
|
311
|
+
event = {
|
|
312
|
+
"type" => "m.room.message",
|
|
313
|
+
"content" => {"msgtype" => "m.text"},
|
|
314
|
+
"event_id" => "$abc123",
|
|
315
|
+
"sender" => "@alice:example.org",
|
|
316
|
+
"origin_server_ts" => 1234567890,
|
|
317
|
+
"room_id" => "!room:example.org"
|
|
318
|
+
}
|
|
319
|
+
Async::Matrix::Schema::Registry.instance.valid?(event).should == false
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
it "is lenient with unknown event types" do
|
|
323
|
+
event = {
|
|
324
|
+
"type" => "m.room.other",
|
|
325
|
+
"content" => {"msgtype" => "m.text", "body" => "hi"},
|
|
326
|
+
"event_id" => "$abc123",
|
|
327
|
+
"sender" => "@alice:example.org",
|
|
328
|
+
"origin_server_ts" => 1234567890,
|
|
329
|
+
"room_id" => "!room:example.org"
|
|
330
|
+
}
|
|
331
|
+
Async::Matrix::Schema::Registry.instance.valid?(event).should == true
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
it "validates m.room.member with correct membership" do
|
|
335
|
+
event = {
|
|
336
|
+
"type" => "m.room.member",
|
|
337
|
+
"content" => {"membership" => "join"},
|
|
338
|
+
"state_key" => "@alice:example.org",
|
|
339
|
+
"event_id" => "$abc123",
|
|
340
|
+
"sender" => "@alice:example.org",
|
|
341
|
+
"origin_server_ts" => 1234567890,
|
|
342
|
+
"room_id" => "!room:example.org"
|
|
343
|
+
}
|
|
344
|
+
Async::Matrix::Schema::Registry.instance.valid?(event).should == true
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
it "rejects m.room.member with invalid membership" do
|
|
348
|
+
event = {
|
|
349
|
+
"type" => "m.room.member",
|
|
350
|
+
"content" => {"membership" => "invalid_state"},
|
|
351
|
+
"state_key" => "@alice:example.org",
|
|
352
|
+
"event_id" => "$abc123",
|
|
353
|
+
"sender" => "@alice:example.org",
|
|
354
|
+
"origin_server_ts" => 1234567890,
|
|
355
|
+
"room_id" => "!room:example.org"
|
|
356
|
+
}
|
|
357
|
+
Async::Matrix::Schema::Registry.instance.valid?(event).should == false
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
it "returns content properties for known types" do
|
|
361
|
+
props = Async::Matrix::Schema::Registry.instance.content_properties("m.room.message")
|
|
362
|
+
props.should.include "msgtype"
|
|
363
|
+
props.should.include "body"
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
it "returns empty content properties for unknown types" do
|
|
367
|
+
Async::Matrix::Schema::Registry.instance.content_properties("m.fake.type").should == []
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
it "performs variant validation for m.room.message with msgtype" do
|
|
371
|
+
event = {
|
|
372
|
+
"type" => "m.room.message",
|
|
373
|
+
"content" => {"msgtype" => "m.text", "body" => "hello"},
|
|
374
|
+
"event_id" => "$abc123",
|
|
375
|
+
"sender" => "@alice:example.org",
|
|
376
|
+
"origin_server_ts" => 1234567890,
|
|
377
|
+
"room_id" => "!room:example.org"
|
|
378
|
+
}
|
|
379
|
+
Async::Matrix::Schema::Registry.instance.validate(event).should == []
|
|
380
|
+
end
|
|
381
|
+
end
|