matrix_sdk 2.0.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -1
- data/lib/matrix_sdk/api.rb +97 -51
- data/lib/matrix_sdk/client.rb +70 -17
- data/lib/matrix_sdk/extensions.rb +5 -1
- data/lib/matrix_sdk/mxid.rb +9 -14
- data/lib/matrix_sdk/protocols/cs.rb +33 -9
- data/lib/matrix_sdk/protocols/msc.rb +57 -15
- data/lib/matrix_sdk/response.rb +3 -1
- data/lib/matrix_sdk/room.rb +68 -25
- data/lib/matrix_sdk/user.rb +8 -0
- data/lib/matrix_sdk/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f16ccd1ed10b02a963b9dbd736e577375ca41b26fb45743bc0344f219b1d70f
|
4
|
+
data.tar.gz: 3d8eef54f71ccf9e04c0da896e6189fd8d4c2c34c269e2890de37dd4cec023a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01de0cccbcf0724a101526190ea4e164ec1235daaa0e0c3d42ed445e760246b2b81a054ba4bd7e88229fdb0833e4fe3a8624a4de3dfd032bfa50b4f23946caf1
|
7
|
+
data.tar.gz: 1b177862e3b01aef4c10de6a4318b8348a5c6e00885f0b137ce13a269bf0d5579e6a72b93a87a9366b8d75ec2549518a7d21f2da5db4d7f1d60fa464ff11d83b
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,41 @@
|
|
1
|
+
## 2.2.0 - 2020-11-20
|
2
|
+
|
3
|
+
- Adds direct message (1:1) room mapping to client abstraction
|
4
|
+
- Adds Api#get_room_event_context (#13)
|
5
|
+
- Improves support for JRuby
|
6
|
+
|
7
|
+
## 2.1.3 - 2020-09-18
|
8
|
+
|
9
|
+
- Adds separate state event handler as Client#on_state_event
|
10
|
+
- Changes Client sync interval to by-default run at full speed
|
11
|
+
- Fixes state events being sent twice if included in both timeline and state of a sync
|
12
|
+
- Improves error reporting of broken 200 responses
|
13
|
+
- Improves event handlers for rooms, to not depend on a specific room object instance anymore
|
14
|
+
|
15
|
+
## 2.1.2 - 2020-09-10
|
16
|
+
|
17
|
+
- Adds method for reading complete member lists for rooms, improves the CS spec adherence
|
18
|
+
- Adds test for state events
|
19
|
+
- Fixes state event handler for rooms not actually passing events
|
20
|
+
- Fixes Api#new_for_domain using a faulty URI in certain cases
|
21
|
+
|
22
|
+
## 2.1.1 - 2020-08-21
|
23
|
+
|
24
|
+
- Fixes crash if state event content is null (#11)
|
25
|
+
- Fixes an uninitialized URI constant exception when requiring only the main library file
|
26
|
+
- Fixes the Api#get_pushrules method missing an ending slash in the request URI
|
27
|
+
- Fixes discovery code for client/server connections based on domain
|
28
|
+
|
29
|
+
## 2.1.0 - 2020-05-22
|
30
|
+
|
31
|
+
- Adds unique query IDs as well as duration in API debug output, to make it easier to track long requests
|
32
|
+
- Finishes up MSC support, get sync over SSE working flawlessly
|
33
|
+
- Exposes the #listen_forever method in the client abstraction
|
34
|
+
- Fixes room access methods
|
35
|
+
|
1
36
|
## 2.0.1 - 2020-03-13
|
2
37
|
|
3
|
-
-
|
38
|
+
- Adds code for handling non-final MSC's in protocols
|
4
39
|
- Currently implementing clients parts of MSC2018 for Sync over Server Sent Events
|
5
40
|
|
6
41
|
## 2.0.0 - 2020-02-14
|
data/lib/matrix_sdk/api.rb
CHANGED
@@ -92,6 +92,8 @@ module MatrixSdk
|
|
92
92
|
uri = URI("http#{ssl ? 's' : ''}://#{domain}")
|
93
93
|
well_known = nil
|
94
94
|
target_uri = nil
|
95
|
+
logger = ::Logging.logger[self]
|
96
|
+
logger.debug "Resolving #{domain}"
|
95
97
|
|
96
98
|
if !port.nil? && !port.empty?
|
97
99
|
# If the domain is fully qualified according to Matrix (FQDN and port) then skip discovery
|
@@ -99,21 +101,30 @@ module MatrixSdk
|
|
99
101
|
elsif target == :server
|
100
102
|
# Attempt SRV record discovery
|
101
103
|
target_uri = begin
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
104
|
+
require 'resolv'
|
105
|
+
resolver = Resolv::DNS.new
|
106
|
+
srv = "_matrix._tcp.#{domain}"
|
107
|
+
logger.debug "Trying DNS #{srv}..."
|
108
|
+
d = resolver.getresource(srv, Resolv::DNS::Resource::IN::SRV)
|
109
|
+
d
|
110
|
+
rescue StandardError => e
|
111
|
+
logger.debug "DNS lookup failed with #{e.class}: #{e.message}"
|
112
|
+
nil
|
113
|
+
end
|
108
114
|
|
109
115
|
if target_uri.nil?
|
110
116
|
# Attempt .well-known discovery for server-to-server
|
111
117
|
well_known = begin
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
118
|
+
wk_uri = URI("https://#{domain}/.well-known/matrix/server")
|
119
|
+
logger.debug "Trying #{wk_uri}..."
|
120
|
+
data = Net::HTTP.start(wk_uri.host, wk_uri.port, use_ssl: true, open_timeout: 5, read_timeout: 5, write_timeout: 5) do |http|
|
121
|
+
http.get(wk_uri.path).body
|
122
|
+
end
|
123
|
+
JSON.parse(data)
|
124
|
+
rescue StandardError => e
|
125
|
+
logger.debug "Well-known failed with #{e.class}: #{e.message}"
|
126
|
+
nil
|
127
|
+
end
|
117
128
|
|
118
129
|
target_uri = well_known['m.server'] if well_known&.key?('m.server')
|
119
130
|
else
|
@@ -122,11 +133,16 @@ module MatrixSdk
|
|
122
133
|
elsif %i[client identity].include? target
|
123
134
|
# Attempt .well-known discovery
|
124
135
|
well_known = begin
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
136
|
+
wk_uri = URI("https://#{domain}/.well-known/matrix/client")
|
137
|
+
logger.debug "Trying #{wk_uri}..."
|
138
|
+
data = Net::HTTP.start(wk_uri.host, wk_uri.port, use_ssl: true, open_timeout: 5, read_timeout: 5, write_timeout: 5) do |http|
|
139
|
+
http.get(wk_uri.path).body
|
140
|
+
end
|
141
|
+
JSON.parse(data)
|
142
|
+
rescue StandardError => e
|
143
|
+
logger.debug "Well-known failed with #{e.class}: #{e.message}"
|
144
|
+
nil
|
145
|
+
end
|
130
146
|
|
131
147
|
if well_known
|
132
148
|
key = 'm.homeserver'
|
@@ -138,6 +154,7 @@ module MatrixSdk
|
|
138
154
|
end
|
139
155
|
end
|
140
156
|
end
|
157
|
+
logger.debug "Using #{target_uri.inspect}"
|
141
158
|
|
142
159
|
# Fall back to direct domain connection
|
143
160
|
target_uri ||= URI("https://#{domain}:8448")
|
@@ -161,6 +178,7 @@ module MatrixSdk
|
|
161
178
|
def protocols
|
162
179
|
self
|
163
180
|
.class.included_modules
|
181
|
+
.reject { |m| m&.name.nil? }
|
164
182
|
.select { |m| m.name.start_with? 'MatrixSdk::Protocols::' }
|
165
183
|
.map { |m| m.name.split('::').last.to_sym }
|
166
184
|
end
|
@@ -250,37 +268,32 @@ module MatrixSdk
|
|
250
268
|
u.query = [u.query, URI.encode_www_form(options.fetch(:query))].flatten.compact.join('&') if options[:query]
|
251
269
|
u.query = nil if u.query.nil? || u.query.empty?
|
252
270
|
end
|
253
|
-
request = Net::HTTP.const_get(method.to_s.capitalize.to_sym).new url.request_uri
|
254
|
-
request.body = options[:body] if options.key? :body
|
255
|
-
request.body = request.body.to_json if options.key?(:body) && !request.body.is_a?(String)
|
256
|
-
request.body_stream = options[:body_stream] if options.key? :body_stream
|
257
|
-
|
258
|
-
global_headers.each { |h, v| request[h] = v }
|
259
|
-
if request.body || request.body_stream
|
260
|
-
request.content_type = 'application/json'
|
261
|
-
request.content_length = (request.body || request.body_stream).size
|
262
|
-
end
|
263
|
-
|
264
|
-
request['authorization'] = "Bearer #{access_token}" if access_token && !options.fetch(:skip_auth, false)
|
265
|
-
if options.key? :headers
|
266
|
-
options[:headers].each do |h, v|
|
267
|
-
request[h.to_s.downcase] = v
|
268
|
-
end
|
269
|
-
end
|
270
271
|
|
271
272
|
failures = 0
|
272
273
|
loop do
|
273
274
|
raise MatrixConnectionError, "Server still too busy to handle request after #{failures} attempts, try again later" if failures >= 10
|
274
275
|
|
275
|
-
|
276
|
+
req_id = ('A'..'Z').to_a.sample(4).join
|
277
|
+
|
278
|
+
req_obj = construct_request(url: url, method: method, **options)
|
279
|
+
print_http(req_obj, id: req_id)
|
276
280
|
begin
|
277
|
-
|
278
|
-
|
281
|
+
dur_start = Time.now
|
282
|
+
response = http.request req_obj
|
283
|
+
dur_end = Time.now
|
284
|
+
duration = dur_end - dur_start
|
285
|
+
rescue EOFError
|
279
286
|
logger.error 'Socket closed unexpectedly'
|
280
|
-
raise
|
287
|
+
raise
|
288
|
+
end
|
289
|
+
print_http(response, duration: duration, id: req_id)
|
290
|
+
|
291
|
+
begin
|
292
|
+
data = JSON.parse(response.body, symbolize_names: true)
|
293
|
+
rescue JSON::JSONError => e
|
294
|
+
logger.debug "#{e.class} error when parsing response. #{e}"
|
295
|
+
data = nil
|
281
296
|
end
|
282
|
-
print_http(response)
|
283
|
-
data = JSON.parse(response.body, symbolize_names: true) rescue nil
|
284
297
|
|
285
298
|
if response.is_a? Net::HTTPTooManyRequests
|
286
299
|
raise MatrixRequestError.new_by_code(data, response.code) unless autoretry
|
@@ -291,24 +304,63 @@ module MatrixSdk
|
|
291
304
|
next
|
292
305
|
end
|
293
306
|
|
294
|
-
|
307
|
+
if response.is_a? Net::HTTPSuccess
|
308
|
+
unless data
|
309
|
+
logger.error "Received non-parsable data in 200 response; #{response.body.inspect}"
|
310
|
+
raise MatrixConnectionError, response
|
311
|
+
end
|
312
|
+
return MatrixSdk::Response.new self, data
|
313
|
+
end
|
295
314
|
raise MatrixRequestError.new_by_code(data, response.code) if data
|
296
315
|
|
297
316
|
raise MatrixConnectionError.class_by_code(response.code), response
|
298
317
|
end
|
299
318
|
end
|
300
319
|
|
320
|
+
# Generate a transaction ID
|
321
|
+
#
|
322
|
+
# @return [String] An arbitrary transaction ID
|
323
|
+
def transaction_id
|
324
|
+
ret = @transaction_id ||= 0
|
325
|
+
@transaction_id = @transaction_id.succ
|
326
|
+
ret
|
327
|
+
end
|
328
|
+
|
301
329
|
private
|
302
330
|
|
303
|
-
def
|
331
|
+
def construct_request(method:, url:, **options)
|
332
|
+
request = Net::HTTP.const_get(method.to_s.capitalize.to_sym).new url.request_uri
|
333
|
+
|
334
|
+
# FIXME: Handle bodies better, avoid duplicating work
|
335
|
+
request.body = options[:body] if options.key? :body
|
336
|
+
request.body = request.body.to_json if options.key?(:body) && !request.body.is_a?(String)
|
337
|
+
request.body_stream = options[:body_stream] if options.key? :body_stream
|
338
|
+
|
339
|
+
global_headers.each { |h, v| request[h] = v }
|
340
|
+
if request.body || request.body_stream
|
341
|
+
request.content_type = 'application/json'
|
342
|
+
request.content_length = (request.body || request.body_stream).size
|
343
|
+
end
|
344
|
+
|
345
|
+
request['authorization'] = "Bearer #{access_token}" if access_token && !options.fetch(:skip_auth, false)
|
346
|
+
if options.key? :headers
|
347
|
+
options[:headers].each do |h, v|
|
348
|
+
request[h.to_s.downcase] = v
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
request
|
353
|
+
end
|
354
|
+
|
355
|
+
def print_http(http, body: true, duration: nil, id: nil)
|
304
356
|
return unless logger.debug?
|
305
357
|
|
306
358
|
if http.is_a? Net::HTTPRequest
|
307
|
-
dir =
|
359
|
+
dir = "#{id ? "#{id} : " : nil}>"
|
308
360
|
logger.debug "#{dir} Sending a #{http.method} request to `#{http.path}`:"
|
309
361
|
else
|
310
|
-
dir =
|
311
|
-
logger.debug "#{dir} Received a #{http.code} #{http.message} response:"
|
362
|
+
dir = "#{id ? "#{id} : " : nil}<"
|
363
|
+
logger.debug "#{dir} Received a #{http.code} #{http.message} response:#{duration ? " [#{(duration * 1000).to_i}ms]" : nil}"
|
312
364
|
end
|
313
365
|
http.to_hash.map { |k, v| "#{k}: #{k == 'authorization' ? '[ REDACTED ]' : v.join(', ')}" }.each do |h|
|
314
366
|
logger.debug "#{dir} #{h}"
|
@@ -316,7 +368,7 @@ module MatrixSdk
|
|
316
368
|
logger.debug dir
|
317
369
|
if body
|
318
370
|
clean_body = JSON.parse(http.body) rescue nil if http.body
|
319
|
-
clean_body.
|
371
|
+
clean_body.each_key { |k| clean_body[k] = '[ REDACTED ]' if %w[password access_token].include?(k) }.to_json if clean_body.is_a? Hash
|
320
372
|
clean_body = clean_body.to_s if clean_body
|
321
373
|
logger.debug "#{dir} #{clean_body.length < 200 ? clean_body : clean_body.slice(0..200) + "... [truncated, #{clean_body.length} Bytes]"}" if clean_body
|
322
374
|
end
|
@@ -324,12 +376,6 @@ module MatrixSdk
|
|
324
376
|
logger.warn "#{e.class} occured while printing request debug; #{e.message}\n#{e.backtrace.join "\n"}"
|
325
377
|
end
|
326
378
|
|
327
|
-
def transaction_id
|
328
|
-
ret = @transaction_id ||= 0
|
329
|
-
@transaction_id = @transaction_id.succ
|
330
|
-
ret
|
331
|
-
end
|
332
|
-
|
333
379
|
def api_to_path(api)
|
334
380
|
# TODO: <api>_current / <api>_latest
|
335
381
|
"/_matrix/#{api.to_s.split('_').join('/')}"
|
data/lib/matrix_sdk/client.rb
CHANGED
@@ -23,7 +23,7 @@ module MatrixSdk
|
|
23
23
|
attr_reader :api, :next_batch
|
24
24
|
attr_accessor :cache, :sync_filter
|
25
25
|
|
26
|
-
events :error, :event, :presence_event, :invite_event, :leave_event, :ephemeral_event
|
26
|
+
events :error, :event, :presence_event, :invite_event, :leave_event, :ephemeral_event, :state_event
|
27
27
|
ignore_inspect :api,
|
28
28
|
:on_event, :on_presence_event, :on_invite_event, :on_leave_event, :on_ephemeral_event
|
29
29
|
|
@@ -44,7 +44,7 @@ module MatrixSdk
|
|
44
44
|
# @see #initialize
|
45
45
|
def self.new_for_domain(domain, **params)
|
46
46
|
api = MatrixSdk::Api.new_for_domain(domain, keep_wellknown: true)
|
47
|
-
return new(api, params) unless api.well_known
|
47
|
+
return new(api, params) unless api.well_known&.key?('m.identity_server')
|
48
48
|
|
49
49
|
identity_server = MatrixSdk::Api.new(api.well_known['m.identity_server']['base_url'], protocols: %i[IS])
|
50
50
|
new(api, params.merge(identity_server: identity_server))
|
@@ -70,8 +70,6 @@ module MatrixSdk
|
|
70
70
|
@api = Api.new hs_url, params
|
71
71
|
end
|
72
72
|
|
73
|
-
@rooms = {}
|
74
|
-
@users = {}
|
75
73
|
@cache = client_cache
|
76
74
|
@identity_server = nil
|
77
75
|
|
@@ -79,7 +77,6 @@ module MatrixSdk
|
|
79
77
|
@sync_thread = nil
|
80
78
|
@sync_filter = { room: { timeline: { limit: params.fetch(:sync_filter_limit, 20) }, state: { lazy_load_members: true } } }
|
81
79
|
|
82
|
-
@should_listen = false
|
83
80
|
@next_batch = nil
|
84
81
|
|
85
82
|
@bad_sync_timeout_limit = 60 * 60
|
@@ -88,6 +85,11 @@ module MatrixSdk
|
|
88
85
|
instance_variable_set("@#{k}", v) if instance_variable_defined? "@#{k}"
|
89
86
|
end
|
90
87
|
|
88
|
+
@rooms = {}
|
89
|
+
@room_handlers = {}
|
90
|
+
@users = {}
|
91
|
+
@should_listen = false
|
92
|
+
|
91
93
|
raise ArgumentError, 'Cache value must be one of of [:all, :some, :none]' unless %i[all some none].include? @cache
|
92
94
|
|
93
95
|
return unless params[:user_id]
|
@@ -154,6 +156,27 @@ module MatrixSdk
|
|
154
156
|
rooms
|
155
157
|
end
|
156
158
|
|
159
|
+
# Gets a list of all direct chat rooms (1:1 chats / direct message chats) for the currenct user
|
160
|
+
#
|
161
|
+
# @return [Hash[String,Array[String]]] A mapping of MXIDs to a list of direct rooms with that user
|
162
|
+
def direct_rooms
|
163
|
+
Hash[api.get_account_data(mxid, 'm.direct').map do |mxid, rooms|
|
164
|
+
[mxid.to_s, rooms]
|
165
|
+
end]
|
166
|
+
end
|
167
|
+
|
168
|
+
# Gets a direct message room for the given user if one exists
|
169
|
+
#
|
170
|
+
# @note Will return the oldest room if multiple exist
|
171
|
+
# @return [Room,nil] A direct message room if one exists
|
172
|
+
def direct_room(mxid)
|
173
|
+
mxid = MatrixSdk::MXID.new mxid.to_s unless mxid.is_a? MatrixSdk::MXID
|
174
|
+
raise ArgumentError, 'Must be a valid user ID' unless mxid.user?
|
175
|
+
|
176
|
+
room_id = direct_rooms[mxid.to_s]&.first
|
177
|
+
ensure_room room_id if room_id
|
178
|
+
end
|
179
|
+
|
157
180
|
# Gets a list of all relevant rooms, either the ones currently handled by
|
158
181
|
# the client, or the list of currently joined ones if no rooms are handled
|
159
182
|
#
|
@@ -343,7 +366,7 @@ module MatrixSdk
|
|
343
366
|
|
344
367
|
# Joins an already created room
|
345
368
|
#
|
346
|
-
# @param room_id_or_alias [String,MXID] A room alias (#room:
|
369
|
+
# @param room_id_or_alias [String,MXID] A room alias (#room:example.com) or a room ID (!id:example.com)
|
347
370
|
# @param server_name [Array[String]] A list of servers to attempt the join through, required for IDs
|
348
371
|
# @return [Room] The resulting room
|
349
372
|
# @see Protocols::CS#join_room
|
@@ -424,12 +447,27 @@ module MatrixSdk
|
|
424
447
|
|
425
448
|
@should_listen = true
|
426
449
|
if api.protocol?(:MSC) && api.msc2108?
|
450
|
+
params[:filter] = sync_filter unless params.key? :filter
|
451
|
+
params[:filter] = params[:filter].to_json unless params[:filter].nil? || params[:filter].is_a?(String)
|
427
452
|
params[:since] = @next_batch if @next_batch
|
428
|
-
|
429
|
-
|
453
|
+
|
454
|
+
errors = 0
|
455
|
+
thread, cancel_token = api.msc2108_sync_sse(params) do |data, event:, id:|
|
430
456
|
@next_batch = id if id
|
431
|
-
|
457
|
+
case event.to_sym
|
458
|
+
when :sync
|
459
|
+
handle_sync_response(data)
|
460
|
+
errors = 0
|
461
|
+
when :sync_error
|
462
|
+
logger.error "SSE Sync error received; #{data.type}: #{data.message}"
|
463
|
+
errors += 1
|
464
|
+
|
465
|
+
# TODO: Allow configuring
|
466
|
+
raise 'Aborting due to excessive errors' if errors >= 5
|
467
|
+
end
|
432
468
|
end
|
469
|
+
|
470
|
+
@should_listen = cancel_token
|
433
471
|
else
|
434
472
|
thread = Thread.new { listen_forever(params) }
|
435
473
|
end
|
@@ -441,8 +479,15 @@ module MatrixSdk
|
|
441
479
|
def stop_listener_thread
|
442
480
|
return unless @sync_thread
|
443
481
|
|
444
|
-
@should_listen
|
445
|
-
|
482
|
+
if @should_listen.is_a? Hash
|
483
|
+
@should_listen[:run] = false
|
484
|
+
else
|
485
|
+
@should_listen = false
|
486
|
+
end
|
487
|
+
if @sync_thread.alive?
|
488
|
+
ret = @sync_thread.join(2)
|
489
|
+
@sync_thread.kill unless ret
|
490
|
+
end
|
446
491
|
@sync_thread = nil
|
447
492
|
end
|
448
493
|
|
@@ -503,9 +548,7 @@ module MatrixSdk
|
|
503
548
|
end
|
504
549
|
end
|
505
550
|
|
506
|
-
|
507
|
-
|
508
|
-
def listen_forever(timeout: 30, bad_sync_timeout: 5, sync_interval: 30, **params)
|
551
|
+
def listen_forever(timeout: 30, bad_sync_timeout: 5, sync_interval: 0, **params)
|
509
552
|
orig_bad_sync_timeout = bad_sync_timeout + 0
|
510
553
|
while @should_listen
|
511
554
|
begin
|
@@ -528,6 +571,8 @@ module MatrixSdk
|
|
528
571
|
fire_error(ErrorEvent.new(e, :listener_thread))
|
529
572
|
end
|
530
573
|
|
574
|
+
private
|
575
|
+
|
531
576
|
def post_authentication(data)
|
532
577
|
@mxid = data[:user_id]
|
533
578
|
@api.access_token = data[:access_token]
|
@@ -539,7 +584,10 @@ module MatrixSdk
|
|
539
584
|
def handle_state(room_id, state_event)
|
540
585
|
return unless state_event.key? :type
|
541
586
|
|
587
|
+
on_state_event.fire(MatrixEvent.new(self, state_event), state_event[:type])
|
588
|
+
|
542
589
|
room = ensure_room(room_id)
|
590
|
+
room.send :put_state_event, state_event
|
543
591
|
content = state_event[:content]
|
544
592
|
case state_event[:type]
|
545
593
|
when 'm.room.name'
|
@@ -553,9 +601,9 @@ module MatrixSdk
|
|
553
601
|
when 'm.room.aliases'
|
554
602
|
room.instance_variable_get('@aliases').concat content[:aliases]
|
555
603
|
when 'm.room.join_rules'
|
556
|
-
room.instance_variable_set '@join_rule', content[:join_rule].to_sym
|
604
|
+
room.instance_variable_set '@join_rule', content[:join_rule].nil? ? nil : content[:join_rule].to_sym
|
557
605
|
when 'm.room.guest_access'
|
558
|
-
room.instance_variable_set '@guest_access', content[:guest_access].to_sym
|
606
|
+
room.instance_variable_set '@guest_access', content[:guest_access].nil? ? nil : content[:guest_access].to_sym
|
559
607
|
when 'm.room.member'
|
560
608
|
return unless cache == :all
|
561
609
|
|
@@ -596,7 +644,12 @@ module MatrixSdk
|
|
596
644
|
|
597
645
|
join[:timeline][:events].each do |event|
|
598
646
|
event[:room_id] = room_id.to_s
|
599
|
-
|
647
|
+
# Avoid sending two identical state events if it's both in state and timeline
|
648
|
+
if event.key?(:state_key)
|
649
|
+
state_event = join.dig(:state, :events).find { |ev| ev[:event_id] == event[:event_id] }
|
650
|
+
|
651
|
+
handle_state(room_id, event) unless event == state_event
|
652
|
+
end
|
600
653
|
room.send :put_event, event
|
601
654
|
|
602
655
|
fire_event(MatrixEvent.new(self, event), event[:type])
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'uri'
|
4
|
+
|
3
5
|
module URI
|
4
6
|
# A mxc:// Matrix content URL
|
5
7
|
class MATRIX < Generic
|
@@ -189,7 +191,9 @@ module MatrixSdk
|
|
189
191
|
end
|
190
192
|
|
191
193
|
def respond_to_missing?(method, *)
|
192
|
-
event.key? method
|
194
|
+
return true if event.key? method
|
195
|
+
|
196
|
+
super
|
193
197
|
end
|
194
198
|
end
|
195
199
|
end
|
data/lib/matrix_sdk/mxid.rb
CHANGED
@@ -32,13 +32,13 @@ module MatrixSdk
|
|
32
32
|
#
|
33
33
|
# @return [String]
|
34
34
|
def homeserver
|
35
|
-
port_s = port ?
|
35
|
+
port_s = port ? ":#{port}" : ''
|
36
36
|
domain ? domain + port_s : ''
|
37
37
|
end
|
38
38
|
|
39
39
|
# Gets the homserver part of the ID as a suffix (':homeserver')
|
40
40
|
def homeserver_suffix
|
41
|
-
|
41
|
+
":#{homeserver}" if domain
|
42
42
|
end
|
43
43
|
|
44
44
|
def to_s
|
@@ -49,18 +49,13 @@ module MatrixSdk
|
|
49
49
|
#
|
50
50
|
# @return [Symbol] The MXID type, one of (:user_id, :room_id, :event_id, :group_id, or :room_alias)
|
51
51
|
def type
|
52
|
-
|
53
|
-
|
54
|
-
:
|
55
|
-
|
56
|
-
:
|
57
|
-
|
58
|
-
|
59
|
-
when '+'
|
60
|
-
:group_id
|
61
|
-
when '#'
|
62
|
-
:room_alias
|
63
|
-
end
|
52
|
+
{
|
53
|
+
'@' => :user_id,
|
54
|
+
'!' => :room_id,
|
55
|
+
'$' => :event_id,
|
56
|
+
'+' => :group_id,
|
57
|
+
'#' => :room_alias
|
58
|
+
}[sigil]
|
64
59
|
end
|
65
60
|
|
66
61
|
# Checks if the ID is valid
|
@@ -767,6 +767,30 @@ module MatrixSdk::Protocols::CS
|
|
767
767
|
request(:get, :client_r0, "/rooms/#{room_id}/state", query: query)
|
768
768
|
end
|
769
769
|
|
770
|
+
# Retrieves number of events that happened just before and after the specified event
|
771
|
+
#
|
772
|
+
# @param room_id [MXID,String] The room to get events from.
|
773
|
+
# @param event_id [MXID,String] The event to get context around.
|
774
|
+
# @option params [Integer] :limit (10) The limit of messages to retrieve
|
775
|
+
# @option params [String] :filter A filter to limit the retrieval to
|
776
|
+
# @return [Response] A response hash with contextual event information
|
777
|
+
# @see https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-rooms-roomid-context-eventid
|
778
|
+
# The Matrix Spec, for more information about the call and response
|
779
|
+
# @example Find event context with filter and limit specified
|
780
|
+
# api.get_room_event_context('#room:example.com', '$event_id:example.com', filter: { types: ['m.room.message'] }.to_json, limit: 20)
|
781
|
+
def get_room_event_context(room_id, event_id, **params)
|
782
|
+
query = {}
|
783
|
+
query[:user_id] = params.delete(:user_id) if protocol?(:AS) && params.key?(:user_id)
|
784
|
+
|
785
|
+
query[:limit] = params.fetch(:limit) if params.key? :limit
|
786
|
+
query[:filter] = params.fetch(:filter) if params.key? :filter
|
787
|
+
|
788
|
+
room_id = ERB::Util.url_encode room_id.to_s
|
789
|
+
event_id = ERB::Util.url_encode event_id.to_s
|
790
|
+
|
791
|
+
request(:get, :client_r0, "/rooms/#{room_id}/context/#{event_id}", query: query)
|
792
|
+
end
|
793
|
+
|
770
794
|
## Specialized getters for specced state
|
771
795
|
#
|
772
796
|
|
@@ -1085,7 +1109,7 @@ module MatrixSdk::Protocols::CS
|
|
1085
1109
|
# @return [Response] The resulting state event
|
1086
1110
|
# @see https://matrix.org/docs/spec/client_server/latest.html#m-room-guest-server-acl
|
1087
1111
|
# The Matrix Spec, for more information about the event and data
|
1088
|
-
def set_room_server_acl(room_id, allow_ip_literals: false,
|
1112
|
+
def set_room_server_acl(room_id, allow:, deny:, allow_ip_literals: false, **params)
|
1089
1113
|
content = {
|
1090
1114
|
allow_ip_literals: allow_ip_literals,
|
1091
1115
|
allow: allow,
|
@@ -1637,7 +1661,7 @@ module MatrixSdk::Protocols::CS
|
|
1637
1661
|
|
1638
1662
|
room_id = ERB::Util.url_encode room_id.to_s
|
1639
1663
|
|
1640
|
-
request(:get, :client_r0, "/rooms/#{room_id}/members", query: query)
|
1664
|
+
request(:get, :client_r0, "/rooms/#{room_id}/members", query: query.merge(params))
|
1641
1665
|
end
|
1642
1666
|
|
1643
1667
|
# Gets a list of the joined members in a room
|
@@ -1712,7 +1736,7 @@ module MatrixSdk::Protocols::CS
|
|
1712
1736
|
# # => { :device_keys => { :'@alice:example.com' => { :ABCDEFGHIJ => { ...
|
1713
1737
|
# @see https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-keys-query
|
1714
1738
|
# The Matrix Spec, for more information about the parameters and data
|
1715
|
-
def keys_query(timeout: nil,
|
1739
|
+
def keys_query(device_keys:, timeout: nil, token: nil, **params)
|
1716
1740
|
body = {
|
1717
1741
|
timeout: (timeout || 10) * 1000,
|
1718
1742
|
device_keys: device_keys
|
@@ -1823,7 +1847,7 @@ module MatrixSdk::Protocols::CS
|
|
1823
1847
|
# @see https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules
|
1824
1848
|
# The Matrix Spec, for more information about the parameters and data
|
1825
1849
|
def get_pushrules
|
1826
|
-
request(:get, :client_r0, '/pushrules')
|
1850
|
+
request(:get, :client_r0, '/pushrules/')
|
1827
1851
|
end
|
1828
1852
|
|
1829
1853
|
# Retrieves a single registered push rule for the current user
|
@@ -1834,7 +1858,7 @@ module MatrixSdk::Protocols::CS
|
|
1834
1858
|
# @return [Response] A response hash containing the full data of the requested push rule
|
1835
1859
|
# @see https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules-scope-kind-ruleid
|
1836
1860
|
# The Matrix Spec, for more information about the parameters and data
|
1837
|
-
def get_pushrule(scope: 'global'
|
1861
|
+
def get_pushrule(kind:, id:, scope: 'global')
|
1838
1862
|
scope = ERB::Util.url_encode scope.to_s
|
1839
1863
|
kind = ERB::Util.url_encode kind.to_s
|
1840
1864
|
id = ERB::Util.url_encode id.to_s
|
@@ -1850,7 +1874,7 @@ module MatrixSdk::Protocols::CS
|
|
1850
1874
|
# @return [Response] A response hash containing an :enabled key for if the rule is enabled or not
|
1851
1875
|
# @see https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules-scope-kind-ruleid-enabled
|
1852
1876
|
# The Matrix Spec, for more information about the parameters and data
|
1853
|
-
def get_pushrule_enabled(scope: 'global'
|
1877
|
+
def get_pushrule_enabled(kind:, id:, scope: 'global')
|
1854
1878
|
scope = ERB::Util.url_encode scope.to_s
|
1855
1879
|
kind = ERB::Util.url_encode kind.to_s
|
1856
1880
|
id = ERB::Util.url_encode id.to_s
|
@@ -1867,7 +1891,7 @@ module MatrixSdk::Protocols::CS
|
|
1867
1891
|
# @return [Response] An empty response hash if the push rule was enabled/disabled successfully
|
1868
1892
|
# @see https://matrix.org/docs/spec/client_server/latest#put-matrix-client-r0-pushrules-scope-kind-ruleid-enabled
|
1869
1893
|
# The Matrix Spec, for more information about the parameters and data
|
1870
|
-
def set_pushrule_enabled(enabled, scope: 'global'
|
1894
|
+
def set_pushrule_enabled(enabled, kind:, id:, scope: 'global')
|
1871
1895
|
scope = ERB::Util.url_encode scope.to_s
|
1872
1896
|
kind = ERB::Util.url_encode kind.to_s
|
1873
1897
|
id = ERB::Util.url_encode id.to_s
|
@@ -1887,7 +1911,7 @@ module MatrixSdk::Protocols::CS
|
|
1887
1911
|
# @return [Response] A response hash containing an :enabled key for if the rule is enabled or not
|
1888
1912
|
# @see https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules-scope-kind-ruleid-actions
|
1889
1913
|
# The Matrix Spec, for more information about the parameters and data
|
1890
|
-
def get_pushrule_actions(scope: 'global'
|
1914
|
+
def get_pushrule_actions(kind:, id:, scope: 'global')
|
1891
1915
|
scope = ERB::Util.url_encode scope.to_s
|
1892
1916
|
kind = ERB::Util.url_encode kind.to_s
|
1893
1917
|
id = ERB::Util.url_encode id.to_s
|
@@ -1904,7 +1928,7 @@ module MatrixSdk::Protocols::CS
|
|
1904
1928
|
# @return [Response] An empty response hash if the push rule actions were modified successfully
|
1905
1929
|
# @see https://matrix.org/docs/spec/client_server/latest#put-matrix-client-r0-pushrules-scope-kind-ruleid-actions
|
1906
1930
|
# The Matrix Spec, for more information about the parameters and data
|
1907
|
-
def set_pushrule_actions(actions, scope: 'global'
|
1931
|
+
def set_pushrule_actions(actions, kind:, id:, scope: 'global')
|
1908
1932
|
scope = ERB::Util.url_encode scope.to_s
|
1909
1933
|
kind = ERB::Util.url_encode kind.to_s
|
1910
1934
|
id = ERB::Util.url_encode id.to_s
|
@@ -2,16 +2,13 @@
|
|
2
2
|
|
3
3
|
# Preliminary support for unmerged MSCs (Matrix Spec Changes)
|
4
4
|
module MatrixSdk::Protocols::MSC
|
5
|
-
def self.included(_)
|
6
|
-
@msc = {}
|
7
|
-
end
|
8
|
-
|
9
5
|
def refresh_mscs
|
10
6
|
@msc = {}
|
11
7
|
end
|
12
8
|
|
13
9
|
# Check if there's support for MSC2108 - Sync over Server Sent Events
|
14
10
|
def msc2108?
|
11
|
+
@msc ||= {}
|
15
12
|
@msc[2108] ||= \
|
16
13
|
begin
|
17
14
|
request(:get, :client_r0, '/sync/sse', skip_auth: true, headers: { accept: 'text/event-stream' })
|
@@ -20,13 +17,13 @@ module MatrixSdk::Protocols::MSC
|
|
20
17
|
rescue MatrixSdk::MatrixRequestError
|
21
18
|
false
|
22
19
|
end
|
20
|
+
rescue StandardError => e
|
21
|
+
logger.debug "Failed to check MSC2108 status;\n#{e.inspect}"
|
22
|
+
false
|
23
23
|
end
|
24
24
|
|
25
25
|
# Sync over Server Sent Events - MSC2108
|
26
26
|
#
|
27
|
-
# @note With the default Ruby Net::HTTP server, body fragments are cached up to 16kB,
|
28
|
-
# which will result in large batches and delays if your filters trim a lot of data.
|
29
|
-
#
|
30
27
|
# @example Syncing over SSE
|
31
28
|
# @since = 'some token'
|
32
29
|
# api.msc2108_sync_sse(since: @since) do |data, event:, id:|
|
@@ -38,10 +35,11 @@ module MatrixSdk::Protocols::MSC
|
|
38
35
|
#
|
39
36
|
# @see Protocols::CS#sync
|
40
37
|
# @see https://github.com/matrix-org/matrix-doc/pull/2108/
|
38
|
+
# rubocop:disable Metrics/MethodLength
|
41
39
|
def msc2108_sync_sse(since: nil, **params, &on_data)
|
42
40
|
raise ArgumentError, 'Must be given a block accepting two args - data and { event:, id: }' \
|
43
41
|
unless on_data.is_a?(Proc) && on_data.arity == 2
|
44
|
-
raise
|
42
|
+
raise 'Needs to be logged in' unless access_token # TODO: Better error
|
45
43
|
|
46
44
|
query = params.select do |k, _v|
|
47
45
|
%i[filter full_state set_presence].include? k
|
@@ -49,24 +47,56 @@ module MatrixSdk::Protocols::MSC
|
|
49
47
|
query[:user_id] = params.delete(:user_id) if protocol?(:AS) && params.key?(:user_id)
|
50
48
|
|
51
49
|
req = Net::HTTP::Get.new(homeserver.dup.tap do |u|
|
52
|
-
u.path = api_to_path
|
50
|
+
u.path = "#{api_to_path :client_r0}/sync/sse"
|
53
51
|
u.query = URI.encode_www_form(query)
|
54
52
|
end)
|
55
53
|
req['accept'] = 'text/event-stream'
|
54
|
+
req['accept-encoding'] = 'identity' # Disable compression on the SSE stream
|
56
55
|
req['authorization'] = "Bearer #{access_token}"
|
57
56
|
req['last-event-id'] = since if since
|
58
57
|
|
58
|
+
cancellation_token = { run: true }
|
59
|
+
|
59
60
|
# rubocop:disable Metrics/BlockLength
|
60
|
-
thread = Thread.new do
|
61
|
+
thread = Thread.new(cancellation_token) do |ctx|
|
61
62
|
print_http(req)
|
62
63
|
http.request req do |response|
|
64
|
+
break unless ctx[:run]
|
65
|
+
|
63
66
|
print_http(response, body: false)
|
64
67
|
raise MatrixRequestError.new_by_code(JSON.parse(response.body, symbolize_names: true), response.code) unless response.is_a? Net::HTTPSuccess
|
65
68
|
|
69
|
+
# Override buffer size for BufferedIO
|
70
|
+
socket = response.instance_variable_get :@socket
|
71
|
+
if socket.is_a? Net::BufferedIO
|
72
|
+
socket.instance_eval do
|
73
|
+
def rbuf_fill
|
74
|
+
bufsize_override = 1024
|
75
|
+
loop do
|
76
|
+
case rv = @io.read_nonblock(bufsize_override, exception: false)
|
77
|
+
when String
|
78
|
+
@rbuf << rv
|
79
|
+
rv.clear
|
80
|
+
return
|
81
|
+
when :wait_readable
|
82
|
+
@io.to_io.wait_readable(@read_timeout) || raise(Net::ReadTimeout)
|
83
|
+
when :wait_writable
|
84
|
+
@io.to_io.wait_writable(@read_timeout) || raise(Net::ReadTimeout)
|
85
|
+
when nil
|
86
|
+
raise EOFError, 'end of file reached'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
stream_id = ('A'..'Z').to_a.sample(4).join
|
94
|
+
|
95
|
+
logger.debug "MSC2108 : #{stream_id} : Starting SSE stream."
|
96
|
+
|
66
97
|
buffer = ''
|
67
98
|
response.read_body do |chunk|
|
68
99
|
buffer += chunk
|
69
|
-
logger.debug "< MSC2108: Received #{chunk.length}B of data."
|
70
100
|
|
71
101
|
while (index = buffer.index(/\r\n\r\n|\n\n/))
|
72
102
|
stream = buffer.slice!(0..index)
|
@@ -86,20 +116,32 @@ module MatrixSdk::Protocols::MSC
|
|
86
116
|
/^id:(.+)$/.match(part) do |m_id|
|
87
117
|
id = m_id[1].strip
|
88
118
|
end
|
119
|
+
/^:(.+)$/.match(part) do |m_comment|
|
120
|
+
logger.debug "MSC2108 : #{stream_id} : Received comment '#{m_comment[1].strip}'"
|
121
|
+
end
|
89
122
|
end
|
90
123
|
|
91
|
-
|
124
|
+
if %w[sync sync_error].include? event
|
125
|
+
data = JSON.parse(data, symbolize_names: true)
|
126
|
+
yield((MatrixSdk::Response.new self, data), event: event, id: id)
|
127
|
+
elsif event
|
128
|
+
logger.info "MSC2108 : #{stream_id} : Received unknown event '#{event}'; #{data}"
|
129
|
+
end
|
130
|
+
end
|
92
131
|
|
93
|
-
|
132
|
+
unless ctx[:run]
|
133
|
+
socket.close
|
134
|
+
break
|
94
135
|
end
|
95
136
|
end
|
137
|
+
break unless ctx[:run]
|
96
138
|
end
|
97
139
|
end
|
98
140
|
# rubocop:enable Metrics/BlockLength
|
99
141
|
|
100
|
-
thread.abort_on_exception = true
|
101
142
|
thread.run
|
102
143
|
|
103
|
-
thread
|
144
|
+
[thread, cancellation_token]
|
104
145
|
end
|
146
|
+
# rubocop:enable Metrics/MethodLength
|
105
147
|
end
|
data/lib/matrix_sdk/response.rb
CHANGED
data/lib/matrix_sdk/room.rb
CHANGED
@@ -42,19 +42,11 @@ module MatrixSdk
|
|
42
42
|
# The timeline events are what will end up in here
|
43
43
|
attr_reader :id, :client, :topic, :aliases, :members, :events
|
44
44
|
|
45
|
-
# @!attribute [r] on_event
|
46
|
-
# @return [EventHandlerArray] The list of event handlers for all events
|
47
|
-
# @!attribute [r] on_state_event
|
48
|
-
# @return [EventHandlerArray] The list of event handlers for only state events
|
49
|
-
# @!attribute [r] on_ephemeral_event
|
50
|
-
# @return [EventHandlerArray] The list of event handlers for only ephemeral events
|
51
|
-
events :event, :state_event, :ephemeral_event
|
52
45
|
# @!method inspect
|
53
46
|
# An inspect method that skips a handful of instance variables to avoid
|
54
47
|
# flooding the terminal with debug data.
|
55
48
|
# @return [String] a regular inspect string without the data for some variables
|
56
|
-
ignore_inspect :client, :members, :events, :prev_batch, :logger
|
57
|
-
:on_event, :on_state_event, :on_ephemeral_event
|
49
|
+
ignore_inspect :client, :members, :events, :prev_batch, :logger
|
58
50
|
|
59
51
|
alias room_id id
|
60
52
|
|
@@ -85,8 +77,6 @@ module MatrixSdk
|
|
85
77
|
room_id = MXID.new room_id unless room_id.is_a?(MXID)
|
86
78
|
raise ArgumentError, 'room_id must be a valid Room ID' unless room_id.room_id?
|
87
79
|
|
88
|
-
event_initialize
|
89
|
-
|
90
80
|
@name = nil
|
91
81
|
@topic = nil
|
92
82
|
@canonical_alias = nil
|
@@ -114,6 +104,28 @@ module MatrixSdk
|
|
114
104
|
logger.debug "Created room #{room_id}"
|
115
105
|
end
|
116
106
|
|
107
|
+
#
|
108
|
+
# Event handlers
|
109
|
+
#
|
110
|
+
|
111
|
+
# @!attribute [r] on_event
|
112
|
+
# @return [EventHandlerArray] The list of event handlers for all events
|
113
|
+
def on_event
|
114
|
+
ensure_room_handlers[:event]
|
115
|
+
end
|
116
|
+
|
117
|
+
# @!attribute [r] on_state_event
|
118
|
+
# @return [EventHandlerArray] The list of event handlers for only state events
|
119
|
+
def on_state_event
|
120
|
+
ensure_room_handlers[:state_event]
|
121
|
+
end
|
122
|
+
|
123
|
+
# @!attribute [r] on_ephemeral_event
|
124
|
+
# @return [EventHandlerArray] The list of event handlers for only ephemeral events
|
125
|
+
def on_ephemeral_event
|
126
|
+
ensure_room_handlers[:ephemeral_event]
|
127
|
+
end
|
128
|
+
|
117
129
|
#
|
118
130
|
# State readers
|
119
131
|
#
|
@@ -157,6 +169,17 @@ module MatrixSdk
|
|
157
169
|
members
|
158
170
|
end
|
159
171
|
|
172
|
+
# Get all members (member events) in the room
|
173
|
+
#
|
174
|
+
# @note This will also count members who've knocked, been invited, have left, or have been banned.
|
175
|
+
#
|
176
|
+
# @param params [Hash] Additional query parameters to pass to the room member listing - e.g. for filtering purposes.
|
177
|
+
#
|
178
|
+
# @return [Array(User)] The complete list of members in the room, regardless of membership state
|
179
|
+
def all_members(**params)
|
180
|
+
client.api.get_room_members(id, **params)[:chunk].map { |ch| client.get_user(ch[:state_key]) }
|
181
|
+
end
|
182
|
+
|
160
183
|
# Gets the current name of the room, querying the API if necessary
|
161
184
|
#
|
162
185
|
# @note Will cache the current name for 15 minutes
|
@@ -340,7 +363,7 @@ module MatrixSdk
|
|
340
363
|
# @param reverse [Boolean] whether to fill messages in reverse or not
|
341
364
|
# @param limit [Integer] the maximum number of messages to backfill
|
342
365
|
# @note This will trigger the `on_event` events as messages are added
|
343
|
-
def backfill_messages(reverse = false, limit = 10)
|
366
|
+
def backfill_messages(reverse = false, limit = 10) # rubocop:disable Style/OptionalBooleanParameter
|
344
367
|
data = client.api.get_room_messages(id, @prev_batch, direction: :b, limit: limit)
|
345
368
|
|
346
369
|
events = data[:chunk]
|
@@ -512,10 +535,10 @@ module MatrixSdk
|
|
512
535
|
# @return [Boolean] if the name was changed or not
|
513
536
|
def reload_name!
|
514
537
|
data = begin
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
538
|
+
client.api.get_room_name(id)
|
539
|
+
rescue MatrixNotFoundError
|
540
|
+
nil
|
541
|
+
end
|
519
542
|
changed = data[:name] != @name
|
520
543
|
@name = data[:name] if changed
|
521
544
|
changed
|
@@ -535,10 +558,10 @@ module MatrixSdk
|
|
535
558
|
# @return [Boolean] if the topic was changed or not
|
536
559
|
def reload_topic!
|
537
560
|
data = begin
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
561
|
+
client.api.get_room_topic(id)
|
562
|
+
rescue MatrixNotFoundError
|
563
|
+
nil
|
564
|
+
end
|
542
565
|
changed = data[:topic] != @topic
|
543
566
|
@topic = data[:topic] if changed
|
544
567
|
changed
|
@@ -590,7 +613,7 @@ module MatrixSdk
|
|
590
613
|
#
|
591
614
|
# @param join_rule [:invite,:public] The join rule of the room
|
592
615
|
def join_rule=(join_rule)
|
593
|
-
client.api.
|
616
|
+
client.api.set_room_join_rules(id, join_rule)
|
594
617
|
@join_rule = join_rule
|
595
618
|
end
|
596
619
|
|
@@ -606,7 +629,7 @@ module MatrixSdk
|
|
606
629
|
#
|
607
630
|
# @param guest_access [:can_join,:forbidden] The new guest access status of the room
|
608
631
|
def guest_access=(guest_access)
|
609
|
-
client.api.
|
632
|
+
client.api.set_room_guest_access(id, guest_access)
|
610
633
|
@guest_access = guest_access
|
611
634
|
end
|
612
635
|
|
@@ -670,15 +693,35 @@ module MatrixSdk
|
|
670
693
|
members << member unless members.any? { |m| m.id == member.id }
|
671
694
|
end
|
672
695
|
|
696
|
+
def room_handlers?
|
697
|
+
client.instance_variable_get(:@room_handlers).key? id
|
698
|
+
end
|
699
|
+
|
700
|
+
def ensure_room_handlers
|
701
|
+
client.instance_variable_get(:@room_handlers)[id] ||= {
|
702
|
+
event: MatrixSdk::EventHandlerArray.new,
|
703
|
+
state_event: MatrixSdk::EventHandlerArray.new,
|
704
|
+
ephemeral_event: MatrixSdk::EventHandlerArray.new
|
705
|
+
}
|
706
|
+
end
|
707
|
+
|
673
708
|
def put_event(event)
|
709
|
+
ensure_room_handlers[:event].fire(MatrixEvent.new(self, event), event[:type]) if room_handlers?
|
710
|
+
|
674
711
|
@events.push event
|
675
712
|
@events.shift if @events.length > @event_history_limit
|
676
|
-
|
677
|
-
fire_event MatrixEvent.new(self, event)
|
678
713
|
end
|
679
714
|
|
680
715
|
def put_ephemeral_event(event)
|
681
|
-
|
716
|
+
return unless room_handlers?
|
717
|
+
|
718
|
+
ensure_room_handlers[:ephemeral_event].fire(MatrixEvent.new(self, event), event[:type])
|
719
|
+
end
|
720
|
+
|
721
|
+
def put_state_event(event)
|
722
|
+
return unless room_handlers?
|
723
|
+
|
724
|
+
ensure_room_handlers[:state_event].fire(MatrixEvent.new(self, event), event[:type])
|
682
725
|
end
|
683
726
|
end
|
684
727
|
end
|
data/lib/matrix_sdk/user.rb
CHANGED
@@ -122,6 +122,14 @@ module MatrixSdk
|
|
122
122
|
Time.now - (since / 1000)
|
123
123
|
end
|
124
124
|
|
125
|
+
# Gets a direct message room with the user if one exists
|
126
|
+
#
|
127
|
+
# @return [Room,nil] A direct message room if one exists
|
128
|
+
# @see MatrixSdk::Client#direct_room
|
129
|
+
def direct_room
|
130
|
+
client.direct_room(id)
|
131
|
+
end
|
132
|
+
|
125
133
|
# Returns all the current device keys for the user, retrieving them if necessary
|
126
134
|
def device_keys
|
127
135
|
@device_keys ||= client.api.keys_query(device_keys: { id => [] }).yield_self do |resp|
|
data/lib/matrix_sdk/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: matrix_sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Olofsson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mocha
|