async-matrix 2.1.0-x86_64-linux → 3.0.1-x86_64-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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +33 -58
  3. data/lib/async/matrix/3.3/async_matrix_e2ee.so +0 -0
  4. data/lib/async/matrix/3.4/async_matrix_e2ee.so +0 -0
  5. data/lib/async/matrix/4.0/async_matrix_e2ee.so +0 -0
  6. data/lib/async/matrix/api/chain.rb +120 -94
  7. data/lib/async/matrix/api/concat.rb +28 -22
  8. data/lib/async/matrix/api/path_tree.rb +71 -44
  9. data/lib/async/matrix/api.rb +6 -1
  10. data/lib/async/matrix/app_service_client.rb +213 -0
  11. data/lib/async/matrix/auth_error.rb +20 -0
  12. data/lib/async/matrix/bad_json_error.rb +20 -0
  13. data/lib/async/matrix/client/encryption.rb +413 -0
  14. data/lib/async/matrix/client/rooms.rb +478 -0
  15. data/lib/async/matrix/client/sync.rb +508 -0
  16. data/lib/async/matrix/client.rb +217 -113
  17. data/lib/async/matrix/config/vivify.rb +107 -0
  18. data/lib/async/matrix/config.rb +184 -0
  19. data/lib/async/matrix/device_store.rb +1621 -0
  20. data/lib/async/matrix/double_puppet_client.rb +1 -1
  21. data/lib/async/matrix/e2ee/pickle_key.rb +182 -0
  22. data/lib/async/matrix/error.rb +9 -36
  23. data/lib/async/matrix/{application_service/error_response.rb → error_response.rb} +10 -10
  24. data/lib/async/matrix/homeserver_error.rb +20 -0
  25. data/lib/async/matrix/invalid_endpoint_error.rb +20 -0
  26. data/lib/async/matrix/media_client.rb +46 -35
  27. data/lib/async/matrix/not_found_error.rb +20 -0
  28. data/lib/async/matrix/notifier.rb +7 -3
  29. data/lib/async/matrix/response_too_large_error.rb +20 -0
  30. data/lib/async/matrix/version.rb +1 -1
  31. data/lib/async/matrix.rb +16 -7
  32. data/lib/protocol/matrix/canonical_json.rb +200 -0
  33. data/lib/protocol/matrix/content.rb +106 -0
  34. data/lib/protocol/matrix/encrypted_message.rb +1018 -0
  35. data/lib/protocol/matrix/error.rb +49 -0
  36. data/lib/protocol/matrix/event.rb +208 -0
  37. data/lib/protocol/matrix/key_backup.rb +347 -0
  38. data/lib/protocol/matrix/keys.rb +381 -0
  39. data/lib/protocol/matrix/message_batch.rb +482 -0
  40. data/lib/protocol/matrix/schema/registry.rb +381 -0
  41. data/lib/protocol/matrix/schema/validation_error.rb +234 -0
  42. data/lib/protocol/matrix/schema.rb +170 -0
  43. data/lib/protocol/matrix/secret_storage.rb +535 -0
  44. data/lib/protocol/matrix/signing.rb +278 -0
  45. data/lib/protocol/matrix.rb +25 -0
  46. metadata +43 -136
  47. data/lib/async/discord/api/path_tree.rb +0 -127
  48. data/lib/async/discord/api.rb +0 -151
  49. data/lib/async/discord/client.rb +0 -283
  50. data/lib/async/discord/error.rb +0 -84
  51. data/lib/async/discord/gateway.rb +0 -359
  52. data/lib/async/discord.rb +0 -15
  53. data/lib/async/matrix/application_service/bot.rb +0 -232
  54. data/lib/async/matrix/application_service/config/schema/analytics.json +0 -21
  55. data/lib/async/matrix/application_service/config/schema/appservice.json +0 -82
  56. data/lib/async/matrix/application_service/config/schema/backfill.json +0 -91
  57. data/lib/async/matrix/application_service/config/schema/bridge.json +0 -209
  58. data/lib/async/matrix/application_service/config/schema/config.json +0 -61
  59. data/lib/async/matrix/application_service/config/schema/database.json +0 -38
  60. data/lib/async/matrix/application_service/config/schema/direct_media.json +0 -35
  61. data/lib/async/matrix/application_service/config/schema/double_puppet.json +0 -24
  62. data/lib/async/matrix/application_service/config/schema/encryption.json +0 -164
  63. data/lib/async/matrix/application_service/config/schema/homeserver.json +0 -58
  64. data/lib/async/matrix/application_service/config/schema/logging.json +0 -50
  65. data/lib/async/matrix/application_service/config/schema/management_room_texts.json +0 -25
  66. data/lib/async/matrix/application_service/config/schema/matrix.json +0 -45
  67. data/lib/async/matrix/application_service/config/schema/permissions.json +0 -54
  68. data/lib/async/matrix/application_service/config/schema/provisioning.json +0 -23
  69. data/lib/async/matrix/application_service/config/schema/public_media.json +0 -39
  70. data/lib/async/matrix/application_service/config/schema/relay.json +0 -43
  71. data/lib/async/matrix/application_service/config/vivify.rb +0 -109
  72. data/lib/async/matrix/application_service/config.rb +0 -225
  73. data/lib/async/matrix/application_service/dispatcher.rb +0 -185
  74. data/lib/async/matrix/application_service/event.rb +0 -285
  75. data/lib/async/matrix/application_service/server.rb +0 -430
  76. data/lib/async/matrix/application_service/transaction.rb +0 -66
  77. data/lib/async/matrix/application_service/transaction_handler.rb +0 -185
  78. data/lib/async/matrix/application_service/transaction_store.rb +0 -80
  79. data/lib/async/matrix/bridge/discord/db/connection.rb +0 -141
  80. data/lib/async/matrix/bridge/discord/db/file.rb +0 -118
  81. data/lib/async/matrix/bridge/discord/db/guild.rb +0 -120
  82. data/lib/async/matrix/bridge/discord/db/message.rb +0 -160
  83. data/lib/async/matrix/bridge/discord/db/migrations/001_create_users.rb +0 -14
  84. data/lib/async/matrix/bridge/discord/db/migrations/002_create_guilds.rb +0 -14
  85. data/lib/async/matrix/bridge/discord/db/migrations/003_create_portals.rb +0 -23
  86. data/lib/async/matrix/bridge/discord/db/migrations/004_create_puppets.rb +0 -19
  87. data/lib/async/matrix/bridge/discord/db/migrations/005_create_messages.rb +0 -20
  88. data/lib/async/matrix/bridge/discord/db/migrations/006_create_reactions.rb +0 -19
  89. data/lib/async/matrix/bridge/discord/db/migrations/007_create_files.rb +0 -18
  90. data/lib/async/matrix/bridge/discord/db/portal.rb +0 -150
  91. data/lib/async/matrix/bridge/discord/db/puppet.rb +0 -128
  92. data/lib/async/matrix/bridge/discord/db/reaction.rb +0 -165
  93. data/lib/async/matrix/bridge/discord/db/schema.rb +0 -18
  94. data/lib/async/matrix/bridge/discord/db/user.rb +0 -112
  95. data/lib/async/matrix/bridge/discord/db.rb +0 -138
  96. data/lib/async/matrix/schema/registry.rb +0 -354
  97. data/lib/async/matrix/schema/validation_error.rb +0 -225
  98. data/lib/async/matrix/schema.rb +0 -170
@@ -1,138 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the Apache License, Version 2.0.
4
- # Copyright, 2026, by General Intelligence Systems.
5
-
6
- require "sequel"
7
- require "sequel/extensions/migration"
8
-
9
- # The Discord bridge's database layer. Requiring this file loads the whole
10
- # subsystem: the Sequel placeholder (schema), the connection helper, and every
11
- # model class, so DB.connect can bind them all.
12
- require_relative "db/schema"
13
- require_relative "db/connection"
14
- require_relative "db/user"
15
- require_relative "db/guild"
16
- require_relative "db/portal"
17
- require_relative "db/puppet"
18
- require_relative "db/message"
19
- require_relative "db/reaction"
20
- require_relative "db/file"
21
-
22
- module Async
23
- module Matrix
24
- module Bridge
25
- module Discord
26
- # Database module for the Discord bridge.
27
- #
28
- # Establishes a connection using the bridge config's database section,
29
- # runs Sequel migrations, and wires up all model classes to the database.
30
- #
31
- # Supports both SQLite (with foreign keys + WAL) and PostgreSQL.
32
- #
33
- # db = Async::Matrix::Bridge::Discord::DB.connect(config)
34
- # # All models are now ready:
35
- # DB::User.create(mxid: "@alice:example.com")
36
- # DB::Portal.where(discord_guild_id: "123").all
37
- #
38
- module DB
39
- MIGRATIONS_PATH = File.join(__dir__, "db", "migrations").freeze
40
-
41
- # Connect to the database, run migrations, and bind all models.
42
- #
43
- # @param config [Async::Matrix::ApplicationService::Config] the bridge config
44
- # @return [Sequel::Database]
45
- def self.connect(config)
46
- db = Connection.establish(config.database)
47
- migrate!(db)
48
- bind_models(db)
49
- db
50
- end
51
-
52
- # Run pending migrations.
53
- #
54
- # @param db [Sequel::Database]
55
- def self.migrate!(db)
56
- Sequel::Migrator.run(db, MIGRATIONS_PATH)
57
- end
58
-
59
- # Bind all model classes to the given database.
60
- #
61
- # @param db [Sequel::Database]
62
- def self.bind_models(db)
63
- Async::Matrix::Bridge::Discord::DB::User.dataset = db[:users]
64
- Async::Matrix::Bridge::Discord::DB::Guild.dataset = db[:guilds]
65
- Async::Matrix::Bridge::Discord::DB::Portal.dataset = db[:portals]
66
- Async::Matrix::Bridge::Discord::DB::Puppet.dataset = db[:puppets]
67
- Async::Matrix::Bridge::Discord::DB::Message.dataset = db[:messages]
68
- Async::Matrix::Bridge::Discord::DB::Reaction.dataset = db[:reactions]
69
- Async::Matrix::Bridge::Discord::DB::CachedFile.dataset = db[:files]
70
- end
71
- end
72
- end
73
- end
74
- end
75
- end
76
-
77
- __END__
78
- describe "Async::Matrix::Bridge::Discord::DB" do
79
- it "connects, migrates, and binds models from config" do
80
- database_config = Object.new
81
- database_config.define_singleton_method(:type) { "sqlite3-fk-wal" }
82
- database_config.define_singleton_method(:uri) { "sqlite:/" }
83
- database_config.define_singleton_method(:max_open_conns) { 1 }
84
-
85
- config = Object.new
86
- config.define_singleton_method(:database) { database_config }
87
-
88
- db = Async::Matrix::Bridge::Discord::DB.connect(config)
89
- db.should.be.kind_of Sequel::Database
90
-
91
- # All tables should exist
92
- db.tables.should.include :users
93
- db.tables.should.include :guilds
94
- db.tables.should.include :portals
95
- db.tables.should.include :puppets
96
- db.tables.should.include :messages
97
- db.tables.should.include :reactions
98
- db.tables.should.include :files
99
-
100
- # Models should be bound and functional
101
- db[:users].delete
102
- db[:guilds].delete
103
- db[:portals].delete
104
- db[:puppets].delete
105
-
106
- Async::Matrix::Bridge::Discord::DB::User.create(mxid: "@db_int:x")
107
- Async::Matrix::Bridge::Discord::DB::User["@db_int:x"].should.not.be.nil
108
-
109
- Async::Matrix::Bridge::Discord::DB::Guild.create(discord_id: "g_int")
110
- Async::Matrix::Bridge::Discord::DB::Guild["g_int"].should.not.be.nil
111
-
112
- Async::Matrix::Bridge::Discord::DB::Portal.create(discord_id: "p_int", receiver: "")
113
- Async::Matrix::Bridge::Discord::DB::Portal["p_int", ""].should.not.be.nil
114
-
115
- Async::Matrix::Bridge::Discord::DB::Puppet.create(discord_id: "d_int")
116
- Async::Matrix::Bridge::Discord::DB::Puppet["d_int"].should.not.be.nil
117
-
118
- db.disconnect
119
- end
120
-
121
- it "exposes MIGRATIONS_PATH" do
122
- File.directory?(Async::Matrix::Bridge::Discord::DB::MIGRATIONS_PATH).should == true
123
- end
124
-
125
- it "is idempotent — running migrations twice does not raise" do
126
- database_config = Object.new
127
- database_config.define_singleton_method(:type) { "sqlite3-fk-wal" }
128
- database_config.define_singleton_method(:uri) { "sqlite:/" }
129
- database_config.define_singleton_method(:max_open_conns) { 1 }
130
-
131
- config = Object.new
132
- config.define_singleton_method(:database) { database_config }
133
-
134
- db = Async::Matrix::Bridge::Discord::DB.connect(config)
135
- lambda { Async::Matrix::Bridge::Discord::DB.migrate!(db) }.should.not.raise
136
- db.disconnect
137
- end
138
- end
@@ -1,354 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the Apache License, Version 2.0.
4
- # Copyright, 2026, by General Intelligence Systems.
5
-
6
- require "yaml"
7
- require "json"
8
- require "json_schemer"
9
- require "pathname"
10
-
11
- module Async
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(GEM_ROOT, "data", "matrix-spec", "event-schemas", "schema")
39
-
40
- @instance = nil
41
-
42
- class << self
43
- # Returns the singleton Registry instance, creating it on first access.
44
- def instance
45
- @instance ||= new
46
- end
47
-
48
- # Reset the singleton (useful for testing).
49
- def reset!
50
- @instance = nil
51
- end
52
- end
53
-
54
- def initialize
55
- @schemas = {}
56
- @variants = {}
57
- @loaded = false
58
- end
59
-
60
- # Look up a schema by Matrix event type (e.g. "m.room.message").
61
- # Returns a JSONSchemer::Schema or nil if no schema exists for that type.
62
- def [](event_type)
63
- load_schemas! unless @loaded
64
- @schemas[event_type]
65
- end
66
-
67
- # Look up a variant schema (e.g. variant("m.room.message", "m.text")).
68
- # Returns a JSONSchemer::Schema or nil.
69
- def variant(event_type, subtype)
70
- load_schemas! unless @loaded
71
- @variants[[event_type, subtype]]
72
- end
73
-
74
- # All known base event types (excludes variant subtypes).
75
- # @return [Array<String>] sorted event type strings
76
- def event_types
77
- load_schemas! unless @loaded
78
- @schemas.keys.sort
79
- end
80
-
81
- # All known variant keys as [event_type, subtype] pairs.
82
- # @return [Array<Array(String, String)>]
83
- def variant_types
84
- load_schemas! unless @loaded
85
- @variants.keys.sort
86
- end
87
-
88
- # Total number of schemas loaded (base + variants).
89
- def size
90
- load_schemas! unless @loaded
91
- @schemas.size + @variants.size
92
- end
93
-
94
- # Validate an event hash against its schema.
95
- # Returns an array of error hashes (empty if valid).
96
- # If no schema exists for the event type, returns empty (lenient).
97
- def validate(event_hash)
98
- event_type = event_hash["type"]
99
- return [] unless event_type
100
-
101
- base = self[event_type]
102
- return [] unless base
103
-
104
- errors = base.validate(event_hash).to_a
105
-
106
- # Also validate against variant if applicable
107
- variant_key = detect_variant_key(event_type, event_hash)
108
- if variant_key
109
- variant_schema = variant(event_type, variant_key)
110
- if variant_schema
111
- errors.concat(variant_schema.validate(event_hash).to_a)
112
- end
113
- end
114
-
115
- errors
116
- end
117
-
118
- # Boolean validation.
119
- def valid?(event_hash)
120
- validate(event_hash).empty?
121
- end
122
-
123
- # Content properties defined by the schema for a given event type.
124
- # Returns an array of property name strings, or empty array if unknown.
125
- def content_properties(event_type)
126
- schema = self[event_type]
127
- return [] unless schema
128
-
129
- extract_content_properties(schema.value)
130
- end
131
-
132
- private
133
-
134
- # Ref resolver that loads YAML/JSON files from disk.
135
- # json_schemer calls this with a URI for each $ref it encounters.
136
- def ref_resolver
137
- @ref_resolver ||= proc do |uri|
138
- path = uri.path
139
- if path && File.exist?(path)
140
- content = File.read(path)
141
- if path.end_with?(".yaml", ".yml")
142
- YAML.safe_load(content, permitted_classes: [Symbol])
143
- else
144
- JSON.parse(content)
145
- end
146
- else
147
- raise JSONSchemer::UnknownRef, uri.to_s
148
- end
149
- end
150
- end
151
-
152
- # Build a JSONSchemer::Schema from a parsed YAML hash, anchored at the
153
- # given file path so relative $ref paths resolve correctly.
154
- def build_schemer(parsed, file_path)
155
- uri = URI("file://#{File.expand_path(file_path)}")
156
- JSONSchemer.schema(
157
- parsed,
158
- base_uri: uri,
159
- ref_resolver: ref_resolver,
160
- insert_property_defaults: false,
161
- formats: MATRIX_FORMATS
162
- )
163
- end
164
-
165
- # Scan the schema directory and load all event schemas.
166
- def load_schemas!
167
- return if @loaded
168
-
169
- Dir.glob(File.join(SCHEMA_DIR, "*.yaml")).each do |path|
170
- load_schema_file(path)
171
- end
172
-
173
- # Also load JSON schema files (a few older schemas are JSON)
174
- Dir.glob(File.join(SCHEMA_DIR, "*.json")).each do |path|
175
- load_schema_file(path)
176
- end
177
-
178
- @loaded = true
179
- end
180
-
181
- def load_schema_file(path)
182
- filename = File.basename(path, File.extname(path))
183
- content = File.read(path)
184
- parsed = path.end_with?(".json") ? JSON.parse(content) : YAML.safe_load(content, permitted_classes: [Symbol])
185
-
186
- schemer = build_schemer(parsed, path)
187
-
188
- # Detect event type from schema: properties.type.enum[0]
189
- declared_type = parsed.dig("properties", "type", "enum")&.first
190
-
191
- if filename.include?("$")
192
- # Variant schema: "m.room.message$m.text" -> base="m.room.message", sub="m.text"
193
- parts = filename.split("$", 2)
194
- base_type = declared_type || parts[0]
195
- subtype = parts[1]
196
- @variants[[base_type, subtype]] = schemer
197
- elsif declared_type
198
- @schemas[declared_type] = schemer
199
- else
200
- # Schemas without a type enum (like core-event-schema/) are skipped
201
- # from the index -- they're only used as $ref targets.
202
- end
203
- rescue => e
204
- # Don't let a single broken schema prevent loading the rest
205
- warn "async-matrix: failed to load schema #{path}: #{e.message}"
206
- end
207
-
208
- # Detect the variant subtype key from an event hash.
209
- # For m.room.message, the variant is the msgtype.
210
- # For m.room.encrypted, the variant is the algorithm.
211
- # For m.key.verification.start, the variant is the method.
212
- def detect_variant_key(event_type, event_hash)
213
- content = event_hash["content"]
214
- return nil unless content.is_a?(Hash)
215
-
216
- case event_type
217
- when "m.room.message"
218
- content["msgtype"]
219
- when "m.room.encrypted"
220
- content["algorithm"]
221
- when "m.key.verification.start"
222
- content["method"]
223
- end
224
- end
225
-
226
- # Extract content property names from a schema's parsed YAML.
227
- def extract_content_properties(schema_hash)
228
- props = schema_hash.dig("properties", "content", "properties")
229
- return [] unless props.is_a?(Hash)
230
- props.keys
231
- end
232
- end
233
- end
234
- end
235
- end
236
-
237
- __END__
238
- describe "Async::Matrix::Schema::Registry" do
239
- it "loads schemas from disk" do
240
- Async::Matrix::Schema::Registry.instance.size.should.be > 0
241
- end
242
-
243
- it "has known event types" do
244
- types = Async::Matrix::Schema::Registry.instance.event_types
245
- types.should.include "m.room.message"
246
- types.should.include "m.room.member"
247
- types.should.include "m.room.create"
248
- types.should.include "m.reaction"
249
- end
250
-
251
- it "returns a JSONSchemer::Schema for a known type" do
252
- schema = Async::Matrix::Schema::Registry.instance["m.room.message"]
253
- schema.should.not.be.nil
254
- schema.should.be.kind_of JSONSchemer::Schema
255
- end
256
-
257
- it "returns nil for an unknown type" do
258
- Async::Matrix::Schema::Registry.instance["m.fake.event"].should.be.nil
259
- end
260
-
261
- it "has variant schemas" do
262
- Async::Matrix::Schema::Registry.instance.variant_types.should.not.be.empty
263
- end
264
-
265
- it "resolves variant schemas" do
266
- schema = Async::Matrix::Schema::Registry.instance.variant("m.room.message", "m.text")
267
- schema.should.not.be.nil
268
- schema.should.be.kind_of JSONSchemer::Schema
269
- end
270
-
271
- it "validates a correct m.room.message event" do
272
- event = {
273
- "type" => "m.room.message",
274
- "content" => {"msgtype" => "m.text", "body" => "hello"},
275
- "event_id" => "$abc123",
276
- "sender" => "@alice:example.org",
277
- "origin_server_ts" => 1234567890,
278
- "room_id" => "!room:example.org"
279
- }
280
- Async::Matrix::Schema::Registry.instance.valid?(event).should == true
281
- end
282
-
283
- it "rejects m.room.message missing body" do
284
- event = {
285
- "type" => "m.room.message",
286
- "content" => {"msgtype" => "m.text"},
287
- "event_id" => "$abc123",
288
- "sender" => "@alice:example.org",
289
- "origin_server_ts" => 1234567890,
290
- "room_id" => "!room:example.org"
291
- }
292
- Async::Matrix::Schema::Registry.instance.valid?(event).should == false
293
- end
294
-
295
- it "is lenient with unknown event types" do
296
- event = {
297
- "type" => "m.room.other",
298
- "content" => {"msgtype" => "m.text", "body" => "hi"},
299
- "event_id" => "$abc123",
300
- "sender" => "@alice:example.org",
301
- "origin_server_ts" => 1234567890,
302
- "room_id" => "!room:example.org"
303
- }
304
- Async::Matrix::Schema::Registry.instance.valid?(event).should == true
305
- end
306
-
307
- it "validates m.room.member with correct membership" do
308
- event = {
309
- "type" => "m.room.member",
310
- "content" => {"membership" => "join"},
311
- "state_key" => "@alice:example.org",
312
- "event_id" => "$abc123",
313
- "sender" => "@alice:example.org",
314
- "origin_server_ts" => 1234567890,
315
- "room_id" => "!room:example.org"
316
- }
317
- Async::Matrix::Schema::Registry.instance.valid?(event).should == true
318
- end
319
-
320
- it "rejects m.room.member with invalid membership" do
321
- event = {
322
- "type" => "m.room.member",
323
- "content" => {"membership" => "invalid_state"},
324
- "state_key" => "@alice:example.org",
325
- "event_id" => "$abc123",
326
- "sender" => "@alice:example.org",
327
- "origin_server_ts" => 1234567890,
328
- "room_id" => "!room:example.org"
329
- }
330
- Async::Matrix::Schema::Registry.instance.valid?(event).should == false
331
- end
332
-
333
- it "returns content properties for known types" do
334
- props = Async::Matrix::Schema::Registry.instance.content_properties("m.room.message")
335
- props.should.include "msgtype"
336
- props.should.include "body"
337
- end
338
-
339
- it "returns empty content properties for unknown types" do
340
- Async::Matrix::Schema::Registry.instance.content_properties("m.fake.type").should == []
341
- end
342
-
343
- it "performs variant validation for m.room.message with msgtype" do
344
- event = {
345
- "type" => "m.room.message",
346
- "content" => {"msgtype" => "m.text", "body" => "hello"},
347
- "event_id" => "$abc123",
348
- "sender" => "@alice:example.org",
349
- "origin_server_ts" => 1234567890,
350
- "room_id" => "!room:example.org"
351
- }
352
- Async::Matrix::Schema::Registry.instance.validate(event).should == []
353
- end
354
- end