async-matrix 2.1.0-x86_64-linux → 3.0.0-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 (80) 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/auth_error.rb +20 -0
  11. data/lib/async/matrix/bad_json_error.rb +20 -0
  12. data/lib/async/matrix/client.rb +142 -110
  13. data/lib/async/matrix/config/vivify.rb +107 -0
  14. data/lib/async/matrix/config.rb +184 -0
  15. data/lib/async/matrix/content.rb +106 -0
  16. data/lib/async/matrix/double_puppet_client.rb +1 -1
  17. data/lib/async/matrix/error.rb +0 -27
  18. data/lib/async/matrix/{application_service/error_response.rb → error_response.rb} +10 -10
  19. data/lib/async/matrix/event.rb +197 -0
  20. data/lib/async/matrix/homeserver_error.rb +20 -0
  21. data/lib/async/matrix/invalid_endpoint_error.rb +20 -0
  22. data/lib/async/matrix/media_client.rb +46 -35
  23. data/lib/async/matrix/not_found_error.rb +20 -0
  24. data/lib/async/matrix/notifier.rb +7 -3
  25. data/lib/async/matrix/response_too_large_error.rb +20 -0
  26. data/lib/async/matrix/schema/registry.rb +367 -340
  27. data/lib/async/matrix/schema/validation_error.rb +221 -214
  28. data/lib/async/matrix/schema.rb +161 -161
  29. data/lib/async/matrix/version.rb +3 -3
  30. data/lib/async/matrix.rb +0 -7
  31. metadata +25 -133
  32. data/lib/async/discord/api/path_tree.rb +0 -127
  33. data/lib/async/discord/api.rb +0 -151
  34. data/lib/async/discord/client.rb +0 -283
  35. data/lib/async/discord/error.rb +0 -84
  36. data/lib/async/discord/gateway.rb +0 -359
  37. data/lib/async/discord.rb +0 -15
  38. data/lib/async/matrix/application_service/bot.rb +0 -232
  39. data/lib/async/matrix/application_service/config/schema/analytics.json +0 -21
  40. data/lib/async/matrix/application_service/config/schema/appservice.json +0 -82
  41. data/lib/async/matrix/application_service/config/schema/backfill.json +0 -91
  42. data/lib/async/matrix/application_service/config/schema/bridge.json +0 -209
  43. data/lib/async/matrix/application_service/config/schema/config.json +0 -61
  44. data/lib/async/matrix/application_service/config/schema/database.json +0 -38
  45. data/lib/async/matrix/application_service/config/schema/direct_media.json +0 -35
  46. data/lib/async/matrix/application_service/config/schema/double_puppet.json +0 -24
  47. data/lib/async/matrix/application_service/config/schema/encryption.json +0 -164
  48. data/lib/async/matrix/application_service/config/schema/homeserver.json +0 -58
  49. data/lib/async/matrix/application_service/config/schema/logging.json +0 -50
  50. data/lib/async/matrix/application_service/config/schema/management_room_texts.json +0 -25
  51. data/lib/async/matrix/application_service/config/schema/matrix.json +0 -45
  52. data/lib/async/matrix/application_service/config/schema/permissions.json +0 -54
  53. data/lib/async/matrix/application_service/config/schema/provisioning.json +0 -23
  54. data/lib/async/matrix/application_service/config/schema/public_media.json +0 -39
  55. data/lib/async/matrix/application_service/config/schema/relay.json +0 -43
  56. data/lib/async/matrix/application_service/config/vivify.rb +0 -109
  57. data/lib/async/matrix/application_service/config.rb +0 -225
  58. data/lib/async/matrix/application_service/dispatcher.rb +0 -185
  59. data/lib/async/matrix/application_service/event.rb +0 -285
  60. data/lib/async/matrix/application_service/server.rb +0 -430
  61. data/lib/async/matrix/application_service/transaction.rb +0 -66
  62. data/lib/async/matrix/application_service/transaction_handler.rb +0 -185
  63. data/lib/async/matrix/application_service/transaction_store.rb +0 -80
  64. data/lib/async/matrix/bridge/discord/db/connection.rb +0 -141
  65. data/lib/async/matrix/bridge/discord/db/file.rb +0 -118
  66. data/lib/async/matrix/bridge/discord/db/guild.rb +0 -120
  67. data/lib/async/matrix/bridge/discord/db/message.rb +0 -160
  68. data/lib/async/matrix/bridge/discord/db/migrations/001_create_users.rb +0 -14
  69. data/lib/async/matrix/bridge/discord/db/migrations/002_create_guilds.rb +0 -14
  70. data/lib/async/matrix/bridge/discord/db/migrations/003_create_portals.rb +0 -23
  71. data/lib/async/matrix/bridge/discord/db/migrations/004_create_puppets.rb +0 -19
  72. data/lib/async/matrix/bridge/discord/db/migrations/005_create_messages.rb +0 -20
  73. data/lib/async/matrix/bridge/discord/db/migrations/006_create_reactions.rb +0 -19
  74. data/lib/async/matrix/bridge/discord/db/migrations/007_create_files.rb +0 -18
  75. data/lib/async/matrix/bridge/discord/db/portal.rb +0 -150
  76. data/lib/async/matrix/bridge/discord/db/puppet.rb +0 -128
  77. data/lib/async/matrix/bridge/discord/db/reaction.rb +0 -165
  78. data/lib/async/matrix/bridge/discord/db/schema.rb +0 -18
  79. data/lib/async/matrix/bridge/discord/db/user.rb +0 -112
  80. data/lib/async/matrix/bridge/discord/db.rb +0 -138
@@ -1,359 +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 "async"
7
- require "async/http/endpoint"
8
- require "async/websocket/client"
9
- require "json"
10
- require "console"
11
-
12
- module Async
13
- module Discord
14
- # WebSocket client for the Discord Gateway (v10).
15
- #
16
- # Connects to Discord's WebSocket gateway, authenticates with a bot token,
17
- # manages heartbeating, and dispatches incoming events to registered handlers.
18
- #
19
- # Supports session resumption on reconnect.
20
- #
21
- # gateway = Async::Discord::Gateway.new(token: "MTk...", intents: 0x30001)
22
- # gateway.on("MESSAGE_CREATE") { |data| puts data["content"] }
23
- # gateway.on("READY") { |data| puts "Connected as #{data["user"]["username"]}" }
24
- # gateway.run # blocks, runs inside Async reactor
25
- #
26
- class Gateway
27
- GATEWAY_URL = "wss://gateway.discord.gg/?v=10&encoding=json"
28
-
29
- # Discord Gateway opcodes
30
- DISPATCH = 0
31
- HEARTBEAT = 1
32
- IDENTIFY = 2
33
- PRESENCE_UPDATE = 3
34
- VOICE_STATE_UPDATE = 4
35
- RESUME = 6
36
- RECONNECT = 7
37
- REQUEST_GUILD_MEMBERS = 8
38
- INVALID_SESSION = 9
39
- HELLO = 10
40
- HEARTBEAT_ACK = 11
41
-
42
- attr_reader :session_id, :seq
43
-
44
- def initialize(token:, intents:, gateway_url: GATEWAY_URL)
45
- @token = token
46
- @intents = intents
47
- @gateway_url = gateway_url
48
- @handlers = Hash.new { |h, k| h[k] = [] }
49
- @seq = nil
50
- @session_id = nil
51
- @resume_url = nil
52
- @heartbeat_interval = nil
53
- @heartbeat_acked = true
54
- @connection = nil
55
- @running = false
56
- end
57
-
58
- # Register a handler for a Discord event type.
59
- #
60
- # gateway.on("MESSAGE_CREATE") { |data| ... }
61
- # gateway.on("READY") { |data| ... }
62
- #
63
- def on(event_type, &block)
64
- @handlers[event_type] << block
65
- end
66
-
67
- # Connect to the gateway and run the event loop.
68
- # Blocks until the connection is closed or an unrecoverable error occurs.
69
- # Must be called inside an Async reactor.
70
- def run
71
- @running = true
72
-
73
- while @running
74
- begin
75
- connect_and_run
76
- rescue => e
77
- Console.error(self) { "Gateway error: #{e.class}: #{e.message}" }
78
- break unless @running
79
- sleep(5)
80
- end
81
- end
82
- end
83
-
84
- # Gracefully stop the gateway.
85
- def stop
86
- @running = false
87
- @connection&.close
88
- end
89
-
90
- # Send a raw payload to the gateway.
91
- def send_payload(op:, d: nil)
92
- return unless @connection
93
-
94
- payload = {op: op, d: d}
95
- @connection.write(payload.to_json)
96
- @connection.flush
97
- end
98
-
99
- private
100
-
101
- def connect_and_run
102
- url = @resume_url || @gateway_url
103
- endpoint = Async::HTTP::Endpoint.parse(url)
104
-
105
- Console.info(self) { "Connecting to #{url}" }
106
-
107
- Async::WebSocket::Client.connect(endpoint) do |connection|
108
- @connection = connection
109
-
110
- # First message should be HELLO
111
- hello = read_message
112
- unless hello && hello["op"] == HELLO
113
- raise GatewayError.new("GATEWAY", "Expected HELLO, got: #{hello&.dig("op")}")
114
- end
115
-
116
- @heartbeat_interval = hello["d"]["heartbeat_interval"] / 1000.0
117
- Console.info(self) { "Heartbeat interval: #{@heartbeat_interval}s" }
118
-
119
- # Start heartbeat fiber
120
- heartbeat_task = Async do
121
- heartbeat_loop
122
- end
123
-
124
- # Identify or resume
125
- if @session_id && @seq
126
- send_resume
127
- else
128
- send_identify
129
- end
130
-
131
- # Read events until disconnected
132
- read_loop
133
-
134
- ensure
135
- heartbeat_task&.stop
136
- @connection = nil
137
- end
138
- end
139
-
140
- def read_message
141
- message = @connection.read
142
- return nil unless message
143
-
144
- JSON.parse(message.to_str)
145
- rescue => e
146
- Console.error(self) { "Failed to read/parse gateway message: #{e.message}" }
147
- nil
148
- end
149
-
150
- def read_loop
151
- loop do
152
- payload = read_message
153
- break unless payload
154
-
155
- handle_payload(payload)
156
- end
157
- end
158
-
159
- def handle_payload(payload)
160
- op = payload["op"]
161
- data = payload["d"]
162
- seq = payload["s"]
163
- type = payload["t"]
164
-
165
- @seq = seq if seq
166
-
167
- case op
168
- when DISPATCH
169
- Console.debug(self) { "DISPATCH: #{type}" }
170
- dispatch(type, data)
171
-
172
- when HEARTBEAT
173
- # Server is asking us to heartbeat immediately
174
- send_heartbeat
175
-
176
- when RECONNECT
177
- Console.info(self) { "Server requested reconnect" }
178
- @connection&.close
179
-
180
- when INVALID_SESSION
181
- resumable = data == true
182
- Console.warn(self) { "Invalid session (resumable=#{resumable})" }
183
- unless resumable
184
- @session_id = nil
185
- @seq = nil
186
- end
187
- sleep(rand(1.0..5.0))
188
- @connection&.close
189
-
190
- when HEARTBEAT_ACK
191
- @heartbeat_acked = true
192
-
193
- else
194
- Console.debug(self) { "Unknown opcode: #{op}" }
195
- end
196
- end
197
-
198
- def dispatch(event_type, data)
199
- case event_type
200
- when "READY"
201
- @session_id = data["session_id"]
202
- @resume_url = data["resume_gateway_url"]
203
- Console.info(self) { "Ready: session=#{@session_id}" }
204
- when "RESUMED"
205
- Console.info(self) { "Resumed successfully" }
206
- end
207
-
208
- @handlers[event_type].each do |handler|
209
- begin
210
- handler.call(data)
211
- rescue => e
212
- Console.error(self) { "Handler for #{event_type} raised: #{e.class}: #{e.message}" }
213
- end
214
- end
215
- end
216
-
217
- def send_identify
218
- send_payload(
219
- op: IDENTIFY,
220
- d: {
221
- token: @token,
222
- intents: @intents,
223
- properties: {
224
- os: RUBY_PLATFORM,
225
- browser: "async-discord",
226
- device: "async-discord"
227
- }
228
- }
229
- )
230
- end
231
-
232
- def send_resume
233
- Console.info(self) { "Resuming session #{@session_id} at seq #{@seq}" }
234
- send_payload(
235
- op: RESUME,
236
- d: {
237
- token: @token,
238
- session_id: @session_id,
239
- seq: @seq
240
- }
241
- )
242
- end
243
-
244
- def send_heartbeat
245
- send_payload(op: HEARTBEAT, d: @seq)
246
- @heartbeat_acked = false
247
- end
248
-
249
- def heartbeat_loop
250
- # Jitter the first heartbeat as per Discord docs
251
- sleep(@heartbeat_interval * rand)
252
- send_heartbeat
253
-
254
- loop do
255
- sleep(@heartbeat_interval)
256
-
257
- unless @heartbeat_acked
258
- Console.warn(self) { "Heartbeat not ACKed, reconnecting" }
259
- @connection&.close
260
- break
261
- end
262
-
263
- send_heartbeat
264
- end
265
- end
266
- end
267
- end
268
- end
269
-
270
- __END__
271
- describe "Async::Discord::Gateway" do
272
- it "initializes with token and intents" do
273
- gw = Async::Discord::Gateway.new(token: "test_token", intents: 0x30001)
274
- gw.session_id.should.be.nil
275
- gw.seq.should.be.nil
276
- end
277
-
278
- it "registers event handlers" do
279
- gw = Async::Discord::Gateway.new(token: "test_token", intents: 0)
280
- received = []
281
- gw.on("MESSAGE_CREATE") { |data| received << data }
282
- gw.on("MESSAGE_CREATE") { |data| received << :second }
283
-
284
- # Dispatch manually via send to test handler registration
285
- gw.send(:dispatch, "MESSAGE_CREATE", {"content" => "hello"})
286
- received.length.should == 2
287
- received[0]["content"].should == "hello"
288
- received[1].should == :second
289
- end
290
-
291
- it "handles READY event and stores session_id" do
292
- gw = Async::Discord::Gateway.new(token: "test_token", intents: 0)
293
- ready_data = {
294
- "session_id" => "abc123",
295
- "resume_gateway_url" => "wss://resume.discord.gg",
296
- "user" => {"username" => "testbot"}
297
- }
298
-
299
- gw.send(:dispatch, "READY", ready_data)
300
- gw.session_id.should == "abc123"
301
- end
302
-
303
- it "updates seq from dispatch payloads" do
304
- gw = Async::Discord::Gateway.new(token: "test_token", intents: 0)
305
- gw.send(:handle_payload, {
306
- "op" => 0,
307
- "d" => {"content" => "hi"},
308
- "s" => 42,
309
- "t" => "MESSAGE_CREATE"
310
- })
311
- gw.seq.should == 42
312
- end
313
-
314
- it "clears session on non-resumable INVALID_SESSION" do
315
- gw = Async::Discord::Gateway.new(token: "test_token", intents: 0)
316
- # Set a session first
317
- gw.send(:dispatch, "READY", {
318
- "session_id" => "sess123",
319
- "resume_gateway_url" => "wss://resume.discord.gg"
320
- })
321
- gw.session_id.should == "sess123"
322
-
323
- # Simulate non-resumable invalid session (stub connection close)
324
- gw.instance_variable_set(:@connection, nil)
325
- gw.send(:handle_payload, {
326
- "op" => Async::Discord::Gateway::INVALID_SESSION,
327
- "d" => false,
328
- "s" => nil,
329
- "t" => nil
330
- })
331
- gw.session_id.should.be.nil
332
- gw.seq.should.be.nil
333
- end
334
-
335
- it "continues dispatching when a handler raises" do
336
- gw = Async::Discord::Gateway.new(token: "test_token", intents: 0)
337
- results = []
338
- gw.on("TEST") { |_| raise "boom" }
339
- gw.on("TEST") { |data| results << data }
340
-
341
- gw.send(:dispatch, "TEST", {"value" => 1})
342
- results.length.should == 1
343
- results.first["value"].should == 1
344
- end
345
-
346
- it "responds to stop" do
347
- gw = Async::Discord::Gateway.new(token: "test_token", intents: 0)
348
- gw.should.respond_to :stop
349
- end
350
-
351
- it "accepts custom gateway URL" do
352
- gw = Async::Discord::Gateway.new(
353
- token: "tok",
354
- intents: 0,
355
- gateway_url: "wss://custom.gateway.example.com"
356
- )
357
- gw.instance_variable_get(:@gateway_url).should == "wss://custom.gateway.example.com"
358
- end
359
- end
data/lib/async/discord.rb DELETED
@@ -1,15 +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 "async/http"
7
-
8
- module Async
9
- module Discord
10
- end
11
- end
12
-
13
- Dir.glob("#{__dir__}/discord/**/*.rb").sort.each do |path|
14
- require path
15
- end
@@ -1,232 +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 "console"
7
-
8
- module Async
9
- module Matrix
10
- module ApplicationService
11
- # DSL wrapper that pairs a Client with event handlers.
12
- #
13
- # A Bot produces handler objects that conform to the TransactionHandler's
14
- # duck-type contract (#event_types, #call). Register a bot on a
15
- # Server (or TransactionHandler) the same way you would register a plain handler.
16
- #
17
- # bot = Bot.new(client) do
18
- # on "m.room.member" do |event|
19
- # join_room(event.room_id) if event.content.membership == "invite"
20
- # end
21
- #
22
- # on "m.room.message", msgtype: "m.text", not_from: :self do |event|
23
- # send_notice event.room_id, "Echo: #{event.content.body}"
24
- # end
25
- # end
26
- #
27
- # server.register(bot)
28
- #
29
- class Bot
30
- attr_reader :client, :handlers
31
-
32
- def initialize(client, &block)
33
- @client = client
34
- @handlers = []
35
-
36
- instance_eval(&block) if block
37
- end
38
-
39
- # Register a handler block for one or more event types.
40
- #
41
- # Filters (all optional):
42
- # msgtype: — only dispatch when content.msgtype matches (e.g. "m.text")
43
- # not_from: — :self skips events sent by this bot's own MXID
44
- #
45
- def on(*event_types, msgtype: nil, not_from: nil, &block)
46
- raise ArgumentError, "on requires at least one event type" if event_types.empty?
47
- raise ArgumentError, "on requires a block" unless block
48
-
49
- handler = Handler.new(
50
- bot: self,
51
- event_types: event_types.flatten,
52
- msgtype: msgtype,
53
- not_from: not_from,
54
- block: block
55
- )
56
-
57
- @handlers << handler
58
- handler
59
- end
60
-
61
- # Internal handler object produced by the #on DSL method.
62
- # Conforms to the TransactionHandler duck-type: #event_types, #call.
63
- class Handler
64
- attr_reader :event_types
65
-
66
- def initialize(bot:, event_types:, msgtype:, not_from:, block:)
67
- @bot = bot
68
- @event_types = event_types
69
- @msgtype = msgtype
70
- @not_from = not_from
71
- @block = block
72
- end
73
-
74
- def call(event)
75
- return if @msgtype && event.content&.msgtype != @msgtype
76
- return if @not_from == :self && event.sender == @bot.client.config.bot_mxid
77
-
78
- # Execute the block in a context that has helper methods
79
- Context.new(@bot.client).execute(event, &@block)
80
- end
81
- end
82
-
83
- # Execution context for handler blocks.
84
- # Provides helper methods so blocks can call send_notice, join_room, etc.
85
- # directly without holding a reference to the client.
86
- class Context
87
- def initialize(client)
88
- @client = client
89
- end
90
-
91
- def execute(event, &block)
92
- @event = event
93
- instance_exec(event, &block)
94
- end
95
-
96
- def send_text(room_id, text)
97
- @client.send_text(room_id, text)
98
- end
99
-
100
- def send_html(room_id, html, plaintext = nil)
101
- @client.send_html(room_id, html, plaintext)
102
- end
103
-
104
- def send_notice(room_id, text)
105
- @client.send_notice(room_id, text)
106
- end
107
-
108
- def join_room(room_id)
109
- @client.join_room(room_id)
110
- end
111
-
112
- def leave_room(room_id)
113
- @client.leave_room(room_id)
114
- end
115
-
116
- def set_display_name(name, user_id = nil)
117
- @client.set_display_name(name, user_id)
118
- end
119
-
120
- def client
121
- @client
122
- end
123
- end
124
- end
125
- end
126
- end
127
- end
128
-
129
- __END__
130
- describe "Async::Matrix::ApplicationService::Bot" do
131
- def make_config
132
- Async::Matrix::ApplicationService::Config.new({
133
- "homeserver" => { "address" => "http://localhost:8008", "domain" => "localhost" },
134
- "appservice" => { "as_token" => "token_secret", "hs_token" => "hs_secret", "bot" => { "username" => "bot" } }
135
- })
136
- end
137
-
138
- def make_event(type:, sender: "@user:localhost", msgtype: nil, body: nil, membership: nil, state_key: nil)
139
- data = {"type" => type, "sender" => sender, "room_id" => "!room:localhost"}
140
- content = {}
141
- content["msgtype"] = msgtype if msgtype
142
- content["body"] = body if body
143
- content["membership"] = membership if membership
144
- data["state_key"] = state_key if state_key
145
- data["content"] = content
146
- Async::Matrix::ApplicationService::Event.new(data)
147
- end
148
-
149
- it "registers handlers via the on DSL" do
150
- config = make_config
151
- client = Async::Matrix::Client.new(config)
152
-
153
- bot = Async::Matrix::ApplicationService::Bot.new(client) do
154
- on "m.room.message" do |event|
155
- # no-op
156
- end
157
- end
158
-
159
- bot.handlers.length.should == 1
160
- bot.handlers.first.event_types.should == ["m.room.message"]
161
- end
162
-
163
- it "registers multiple event types on a single handler" do
164
- config = make_config
165
- client = Async::Matrix::Client.new(config)
166
-
167
- bot = Async::Matrix::ApplicationService::Bot.new(client) do
168
- on "m.room.message", "m.room.member" do |event|
169
- # no-op
170
- end
171
- end
172
-
173
- bot.handlers.first.event_types.should == ["m.room.message", "m.room.member"]
174
- end
175
-
176
- it "filters by msgtype" do
177
- config = make_config
178
- client = Async::Matrix::Client.new(config)
179
- received = []
180
-
181
- bot = Async::Matrix::ApplicationService::Bot.new(client) do
182
- on "m.room.message", msgtype: "m.text" do |event|
183
- received << event.content.body
184
- end
185
- end
186
-
187
- handler = bot.handlers.first
188
- handler.call(make_event(type: "m.room.message", msgtype: "m.text", body: "hello"))
189
- handler.call(make_event(type: "m.room.message", msgtype: "m.notice", body: "ignored"))
190
-
191
- received.should == ["hello"]
192
- end
193
-
194
- it "filters out self with not_from: :self" do
195
- config = make_config
196
- client = Async::Matrix::Client.new(config)
197
- received = []
198
-
199
- bot = Async::Matrix::ApplicationService::Bot.new(client) do
200
- on "m.room.message", not_from: :self do |event|
201
- received << event.content.body
202
- end
203
- end
204
-
205
- handler = bot.handlers.first
206
- handler.call(make_event(type: "m.room.message", sender: "@user:localhost", msgtype: "m.text", body: "yes"))
207
- handler.call(make_event(type: "m.room.message", sender: "@bot:localhost", msgtype: "m.text", body: "no"))
208
-
209
- received.should == ["yes"]
210
- end
211
-
212
- it "raises if on is called without event types" do
213
- config = make_config
214
- client = Async::Matrix::Client.new(config)
215
-
216
- lambda {
217
- Async::Matrix::ApplicationService::Bot.new(client) do
218
- on do |event|; end
219
- end
220
- }.should.raise(ArgumentError)
221
- end
222
-
223
- it "raises if on is called without a block" do
224
- config = make_config
225
- client = Async::Matrix::Client.new(config)
226
-
227
- lambda {
228
- bot = Async::Matrix::ApplicationService::Bot.new(client)
229
- bot.on "m.room.message"
230
- }.should.raise(ArgumentError)
231
- end
232
- end
@@ -1,21 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "analytics.json",
4
- "description": "Analytics/telemetry settings. Maps to mautrix bridgev2/bridgeconfig.AnalyticsConfig.",
5
- "type": "object",
6
- "properties": {
7
- "token": {
8
- "type": "string",
9
- "description": "Analytics token for the telemetry backend."
10
- },
11
- "url": {
12
- "type": "string",
13
- "description": "URL of the analytics/telemetry endpoint."
14
- },
15
- "user_id": {
16
- "type": "string",
17
- "description": "User ID to associate with analytics events."
18
- }
19
- },
20
- "additionalProperties": false
21
- }