matrix_sdk 2.0.1 → 2.2.0
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/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
|