matrix_sdk 2.1.3 → 2.5.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 +31 -0
- data/README.md +1 -1
- data/lib/matrix_sdk/api.rb +49 -32
- data/lib/matrix_sdk/client.rb +71 -54
- data/lib/matrix_sdk/errors.rb +4 -0
- data/lib/matrix_sdk/mxid.rb +50 -15
- data/lib/matrix_sdk/protocols/cs.rb +182 -124
- data/lib/matrix_sdk/protocols/msc.rb +5 -1
- data/lib/matrix_sdk/response.rb +3 -1
- data/lib/matrix_sdk/room.rb +335 -102
- data/lib/matrix_sdk/rooms/space.rb +79 -0
- data/lib/matrix_sdk/user.rb +11 -3
- data/lib/matrix_sdk/util/events.rb +111 -0
- data/lib/matrix_sdk/util/extensions.rb +75 -0
- data/lib/matrix_sdk/util/tinycache.rb +134 -0
- data/lib/matrix_sdk/util/tinycache_adapter.rb +77 -0
- data/lib/matrix_sdk/util/uri.rb +89 -0
- data/lib/matrix_sdk/version.rb +1 -1
- data/lib/matrix_sdk.rb +16 -1
- metadata +12 -8
- data/lib/matrix_sdk/application_service.rb +0 -212
- data/lib/matrix_sdk/extensions.rb +0 -197
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24a67aeb6af66f75480104c5c0dc44987e2fe54163ed96047da58bf091476752
|
4
|
+
data.tar.gz: e5935a94b430a1b195b55d748415cc0ad95ea649e32f5e97045cc82726dd2bd3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ea88ea4c76b573dad7b03aeba49e91b8f7c01040118c38032b49ca00cfbe687bd931c4e17387545e27df529f6ae06fc835ee964b5e79489fb0c5cf84186b35b
|
7
|
+
data.tar.gz: e2a6a5cd78e7629ffb2cc4af5ec9c9154f2f63db570479ebb2c6fa9aff13b7b231bea877d56694ae799019698af8d4a87394f88fa162dcb172dbbd1ede09fc8f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,34 @@
|
|
1
|
+
## 2.5.0 - 2022-01-14
|
2
|
+
|
3
|
+
- Adds preliminary support for the Matrix v1.1 `client/v3` API
|
4
|
+
- Adds some support for knocking rooms
|
5
|
+
- Adds mutex synchronization on API requests to avoid some threading issues
|
6
|
+
- Fixes error on attempting to skip cache for certain requests (#19)
|
7
|
+
- Fixes inconsistency in MXID typing for the Client abstraction (#18 #20)
|
8
|
+
- Fixes missed autoloader entries for errors (#22)
|
9
|
+
- Fixes some potential issues arising from broken user-provided state data
|
10
|
+
|
11
|
+
## 2.4.0 - 2021-07-19
|
12
|
+
|
13
|
+
- Adds support for matrix: URI's according to MSC2312
|
14
|
+
- Adds some basic support for detecting Spaces (MSC1772)
|
15
|
+
- Fixes sync against Synapse 1.38.0 missing empty fields
|
16
|
+
|
17
|
+
## 2.3.0 - 2021-03-26
|
18
|
+
|
19
|
+
- Adds support for Ruby 3.0 (#15)
|
20
|
+
- Adds support for requests against the Synapse admin API
|
21
|
+
- Adds helper methods for checking and changing user power levels
|
22
|
+
- Adds a proper caching system for room data
|
23
|
+
- Fixes argument error in `#get_room_messages`
|
24
|
+
- Removes unfinished and broken AS abstraction
|
25
|
+
|
26
|
+
## 2.2.0 - 2020-11-20
|
27
|
+
|
28
|
+
- Adds direct message (1:1) room mapping to client abstraction
|
29
|
+
- Adds Api#get_room_event_context (#13)
|
30
|
+
- Improves support for JRuby
|
31
|
+
|
1
32
|
## 2.1.3 - 2020-09-18
|
2
33
|
|
3
34
|
- Adds separate state event handler as Client#on_state_event
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ A Ruby gem for easing the development of software that communicates with servers
|
|
4
4
|
|
5
5
|
There is a Matrix room for the discussion about usage and development at [#ruby-matrix-sdk:kittenface.studio](https://matrix.to/#/#ruby-matrix-sdk:kittenface.studio).
|
6
6
|
|
7
|
-
Live YARD documentation can be found at;
|
7
|
+
Live YARD documentation can be found at; https://ruby-sdk.ananace.dev
|
8
8
|
|
9
9
|
## Example usage
|
10
10
|
|
data/lib/matrix_sdk/api.rb
CHANGED
@@ -38,6 +38,7 @@ module MatrixSdk
|
|
38
38
|
# @option params [Numeric] :read_timeout (240) The timeout in seconds for reading responses
|
39
39
|
# @option params [Hash] :global_headers Additional headers to set for all requests
|
40
40
|
# @option params [Boolean] :skip_login Should the API skip logging in if the HS URL contains user information
|
41
|
+
# @option params [Boolean] :synapse (true) Is the API connecting to a Synapse instance
|
41
42
|
# @option params [Hash] :well_known The .well-known object that the server was discovered through, should not be set manually
|
42
43
|
def initialize(homeserver, **params)
|
43
44
|
@homeserver = homeserver
|
@@ -56,12 +57,14 @@ module MatrixSdk
|
|
56
57
|
@validate_certificate = params.fetch(:validate_certificate, false)
|
57
58
|
@transaction_id = params.fetch(:transaction_id, 0)
|
58
59
|
@backoff_time = params.fetch(:backoff_time, 5000)
|
59
|
-
@open_timeout = params.fetch(:open_timeout,
|
60
|
-
@read_timeout = params.fetch(:read_timeout,
|
60
|
+
@open_timeout = params.fetch(:open_timeout, nil)
|
61
|
+
@read_timeout = params.fetch(:read_timeout, nil)
|
61
62
|
@well_known = params.fetch(:well_known, {})
|
62
63
|
@global_headers = DEFAULT_HEADERS.dup
|
63
64
|
@global_headers.merge!(params.fetch(:global_headers)) if params.key? :global_headers
|
65
|
+
@synapse = params.fetch(:synapse, true)
|
64
66
|
@http = nil
|
67
|
+
@http_lock = Mutex.new
|
65
68
|
|
66
69
|
([params.fetch(:protocols, [:CS])].flatten - protocols).each do |proto|
|
67
70
|
self.class.include MatrixSdk::Protocols.const_get(proto)
|
@@ -161,11 +164,13 @@ module MatrixSdk
|
|
161
164
|
|
162
165
|
params[:well_known] = well_known if keep_wellknown
|
163
166
|
|
164
|
-
new(
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
167
|
+
new(
|
168
|
+
uri,
|
169
|
+
**params.merge(
|
170
|
+
address: target_uri.host,
|
171
|
+
port: target_uri.port
|
172
|
+
)
|
173
|
+
)
|
169
174
|
end
|
170
175
|
|
171
176
|
# Get a list of enabled protocols on the API client
|
@@ -268,23 +273,6 @@ module MatrixSdk
|
|
268
273
|
u.query = [u.query, URI.encode_www_form(options.fetch(:query))].flatten.compact.join('&') if options[:query]
|
269
274
|
u.query = nil if u.query.nil? || u.query.empty?
|
270
275
|
end
|
271
|
-
request = Net::HTTP.const_get(method.to_s.capitalize.to_sym).new url.request_uri
|
272
|
-
request.body = options[:body] if options.key? :body
|
273
|
-
request.body = request.body.to_json if options.key?(:body) && !request.body.is_a?(String)
|
274
|
-
request.body_stream = options[:body_stream] if options.key? :body_stream
|
275
|
-
|
276
|
-
global_headers.each { |h, v| request[h] = v }
|
277
|
-
if request.body || request.body_stream
|
278
|
-
request.content_type = 'application/json'
|
279
|
-
request.content_length = (request.body || request.body_stream).size
|
280
|
-
end
|
281
|
-
|
282
|
-
request['authorization'] = "Bearer #{access_token}" if access_token && !options.fetch(:skip_auth, false)
|
283
|
-
if options.key? :headers
|
284
|
-
options[:headers].each do |h, v|
|
285
|
-
request[h.to_s.downcase] = v
|
286
|
-
end
|
287
|
-
end
|
288
276
|
|
289
277
|
failures = 0
|
290
278
|
loop do
|
@@ -292,10 +280,13 @@ module MatrixSdk
|
|
292
280
|
|
293
281
|
req_id = ('A'..'Z').to_a.sample(4).join
|
294
282
|
|
295
|
-
|
296
|
-
|
283
|
+
req_obj = construct_request(url: url, method: method, **options)
|
284
|
+
print_http(req_obj, id: req_id)
|
285
|
+
response = duration = nil
|
286
|
+
|
287
|
+
@http_lock.synchronize do
|
297
288
|
dur_start = Time.now
|
298
|
-
response = http.request
|
289
|
+
response = http.request req_obj
|
299
290
|
dur_end = Time.now
|
300
291
|
duration = dur_end - dur_start
|
301
292
|
rescue EOFError
|
@@ -344,14 +335,38 @@ module MatrixSdk
|
|
344
335
|
|
345
336
|
private
|
346
337
|
|
338
|
+
def construct_request(method:, url:, **options)
|
339
|
+
request = Net::HTTP.const_get(method.to_s.capitalize.to_sym).new url.request_uri
|
340
|
+
|
341
|
+
# FIXME: Handle bodies better, avoid duplicating work
|
342
|
+
request.body = options[:body] if options.key? :body
|
343
|
+
request.body = request.body.to_json if options.key?(:body) && !request.body.is_a?(String)
|
344
|
+
request.body_stream = options[:body_stream] if options.key? :body_stream
|
345
|
+
|
346
|
+
global_headers.each { |h, v| request[h] = v }
|
347
|
+
if request.body || request.body_stream
|
348
|
+
request.content_type = 'application/json'
|
349
|
+
request.content_length = (request.body || request.body_stream).size
|
350
|
+
end
|
351
|
+
|
352
|
+
request['authorization'] = "Bearer #{access_token}" if access_token && !options.fetch(:skip_auth, false)
|
353
|
+
if options.key? :headers
|
354
|
+
options[:headers].each do |h, v|
|
355
|
+
request[h.to_s.downcase] = v
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
request
|
360
|
+
end
|
361
|
+
|
347
362
|
def print_http(http, body: true, duration: nil, id: nil)
|
348
363
|
return unless logger.debug?
|
349
364
|
|
350
365
|
if http.is_a? Net::HTTPRequest
|
351
|
-
dir = "#{id ? id
|
366
|
+
dir = "#{id ? "#{id} : " : nil}>"
|
352
367
|
logger.debug "#{dir} Sending a #{http.method} request to `#{http.path}`:"
|
353
368
|
else
|
354
|
-
dir = "#{id ? id
|
369
|
+
dir = "#{id ? "#{id} : " : nil}<"
|
355
370
|
logger.debug "#{dir} Received a #{http.code} #{http.message} response:#{duration ? " [#{(duration * 1000).to_i}ms]" : nil}"
|
356
371
|
end
|
357
372
|
http.to_hash.map { |k, v| "#{k}: #{k == 'authorization' ? '[ REDACTED ]' : v.join(', ')}" }.each do |h|
|
@@ -360,7 +375,7 @@ module MatrixSdk
|
|
360
375
|
logger.debug dir
|
361
376
|
if body
|
362
377
|
clean_body = JSON.parse(http.body) rescue nil if http.body
|
363
|
-
clean_body.
|
378
|
+
clean_body.each_key { |k| clean_body[k] = '[ REDACTED ]' if %w[password access_token].include?(k) }.to_json if clean_body.is_a? Hash
|
364
379
|
clean_body = clean_body.to_s if clean_body
|
365
380
|
logger.debug "#{dir} #{clean_body.length < 200 ? clean_body : clean_body.slice(0..200) + "... [truncated, #{clean_body.length} Bytes]"}" if clean_body
|
366
381
|
end
|
@@ -369,6 +384,8 @@ module MatrixSdk
|
|
369
384
|
end
|
370
385
|
|
371
386
|
def api_to_path(api)
|
387
|
+
return "/_synapse/#{api.to_s.split('_').join('/')}" if @synapse && api.to_s.start_with?('admin_')
|
388
|
+
|
372
389
|
# TODO: <api>_current / <api>_latest
|
373
390
|
"/_matrix/#{api.to_s.split('_').join('/')}"
|
374
391
|
end
|
@@ -384,8 +401,8 @@ module MatrixSdk
|
|
384
401
|
Net::HTTP.new(host, port)
|
385
402
|
end
|
386
403
|
|
387
|
-
@http.open_timeout = open_timeout
|
388
|
-
@http.read_timeout = read_timeout
|
404
|
+
@http.open_timeout = open_timeout if open_timeout
|
405
|
+
@http.read_timeout = read_timeout if read_timeout
|
389
406
|
@http.use_ssl = homeserver.scheme == 'https'
|
390
407
|
@http.verify_mode = validate_certificate ? ::OpenSSL::SSL::VERIFY_PEER : ::OpenSSL::SSL::VERIFY_NONE
|
391
408
|
@http.start
|
data/lib/matrix_sdk/client.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'matrix_sdk'
|
4
|
+
require 'matrix_sdk/util/events'
|
4
5
|
|
5
6
|
require 'English'
|
6
7
|
require 'forwardable'
|
@@ -67,11 +68,12 @@ module MatrixSdk
|
|
67
68
|
api.instance_variable_set("@#{k}", v) if api.instance_variable_defined? "@#{k}"
|
68
69
|
end
|
69
70
|
else
|
70
|
-
@api = Api.new hs_url, params
|
71
|
+
@api = Api.new hs_url, **params
|
71
72
|
end
|
72
73
|
|
73
74
|
@cache = client_cache
|
74
75
|
@identity_server = nil
|
76
|
+
@mxid = nil
|
75
77
|
|
76
78
|
@sync_token = nil
|
77
79
|
@sync_thread = nil
|
@@ -101,9 +103,8 @@ module MatrixSdk
|
|
101
103
|
#
|
102
104
|
# @return [MXID] The MXID of the current user
|
103
105
|
def mxid
|
104
|
-
@mxid ||=
|
105
|
-
|
106
|
-
end
|
106
|
+
@mxid ||= MXID.new api.whoami?[:user_id] if api&.access_token
|
107
|
+
@mxid
|
107
108
|
end
|
108
109
|
|
109
110
|
alias user_id mxid
|
@@ -156,6 +157,25 @@ module MatrixSdk
|
|
156
157
|
rooms
|
157
158
|
end
|
158
159
|
|
160
|
+
# Gets a list of all direct chat rooms (1:1 chats / direct message chats) for the currenct user
|
161
|
+
#
|
162
|
+
# @return [Hash[String,Array[String]]] A mapping of MXIDs to a list of direct rooms with that user
|
163
|
+
def direct_rooms
|
164
|
+
api.get_account_data(mxid, 'm.direct').transform_keys(&:to_s)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Gets a direct message room for the given user if one exists
|
168
|
+
#
|
169
|
+
# @note Will return the oldest room if multiple exist
|
170
|
+
# @return [Room,nil] A direct message room if one exists
|
171
|
+
def direct_room(mxid)
|
172
|
+
mxid = MatrixSdk::MXID.new mxid.to_s unless mxid.is_a? MatrixSdk::MXID
|
173
|
+
raise ArgumentError, 'Must be a valid user ID' unless mxid.user?
|
174
|
+
|
175
|
+
room_id = direct_rooms[mxid.to_s]&.first
|
176
|
+
ensure_room room_id if room_id
|
177
|
+
end
|
178
|
+
|
159
179
|
# Gets a list of all relevant rooms, either the ones currently handled by
|
160
180
|
# the client, or the list of currently joined ones if no rooms are handled
|
161
181
|
#
|
@@ -172,6 +192,19 @@ module MatrixSdk
|
|
172
192
|
@rooms.values
|
173
193
|
end
|
174
194
|
|
195
|
+
# Get a list of all joined Matrix Spaces
|
196
|
+
#
|
197
|
+
# @return [Array[Room]] All the currently joined Spaces
|
198
|
+
def spaces
|
199
|
+
rooms = if cache == :none
|
200
|
+
api.get_joined_rooms.joined_rooms.map { |id| Room.new(self, id) }
|
201
|
+
else
|
202
|
+
self.rooms
|
203
|
+
end
|
204
|
+
|
205
|
+
rooms.select(&:space?)
|
206
|
+
end
|
207
|
+
|
175
208
|
# Refresh the list of currently handled rooms, replacing it with the user's
|
176
209
|
# currently joined rooms.
|
177
210
|
#
|
@@ -189,6 +222,7 @@ module MatrixSdk
|
|
189
222
|
true
|
190
223
|
end
|
191
224
|
alias refresh_rooms! reload_rooms!
|
225
|
+
alias reload_spaces! reload_rooms!
|
192
226
|
|
193
227
|
# Register - and log in - on the connected HS as a guest
|
194
228
|
#
|
@@ -339,7 +373,7 @@ module MatrixSdk
|
|
339
373
|
# @return [Room] The resulting room
|
340
374
|
# @see Protocols::CS#create_room
|
341
375
|
def create_room(room_alias = nil, **params)
|
342
|
-
data = api.create_room(params.merge(room_alias: room_alias))
|
376
|
+
data = api.create_room(**params.merge(room_alias: room_alias))
|
343
377
|
ensure_room(data.room_id)
|
344
378
|
end
|
345
379
|
|
@@ -407,13 +441,13 @@ module MatrixSdk
|
|
407
441
|
|
408
442
|
# Upload a piece of data to the media repo
|
409
443
|
#
|
410
|
-
# @return [URI::
|
444
|
+
# @return [URI::MXC] A Matrix content (mxc://) URL pointing to the uploaded data
|
411
445
|
# @param content [String] The data to upload
|
412
446
|
# @param content_type [String] The MIME type of the data
|
413
447
|
# @see Protocols::CS#media_upload
|
414
448
|
def upload(content, content_type)
|
415
449
|
data = api.media_upload(content, content_type)
|
416
|
-
return data[:content_uri] if data.key? :content_uri
|
450
|
+
return URI(data[:content_uri]) if data.key? :content_uri
|
417
451
|
|
418
452
|
raise MatrixUnexpectedResponseError, 'Upload succeeded, but no media URI returned'
|
419
453
|
end
|
@@ -433,10 +467,11 @@ module MatrixSdk
|
|
433
467
|
errors = 0
|
434
468
|
thread, cancel_token = api.msc2108_sync_sse(params) do |data, event:, id:|
|
435
469
|
@next_batch = id if id
|
436
|
-
|
470
|
+
case event.to_sym
|
471
|
+
when :sync
|
437
472
|
handle_sync_response(data)
|
438
473
|
errors = 0
|
439
|
-
|
474
|
+
when :sync_error
|
440
475
|
logger.error "SSE Sync error received; #{data.type}: #{data.message}"
|
441
476
|
errors += 1
|
442
477
|
|
@@ -447,7 +482,7 @@ module MatrixSdk
|
|
447
482
|
|
448
483
|
@should_listen = cancel_token
|
449
484
|
else
|
450
|
-
thread = Thread.new { listen_forever(params) }
|
485
|
+
thread = Thread.new { listen_forever(**params) }
|
451
486
|
end
|
452
487
|
@sync_thread = thread
|
453
488
|
thread.run
|
@@ -495,11 +530,9 @@ module MatrixSdk
|
|
495
530
|
|
496
531
|
attempts = 0
|
497
532
|
data = loop do
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
raise e if (attempts += 1) >= params.fetch(:allow_sync_retry, 0)
|
502
|
-
end
|
533
|
+
break api.sync(**extra_params)
|
534
|
+
rescue MatrixSdk::MatrixTimeoutError => e
|
535
|
+
raise e if (attempts += 1) >= params.fetch(:allow_sync_retry, 0)
|
503
536
|
end
|
504
537
|
|
505
538
|
@next_batch = data[:next_batch] unless skip_store_batch
|
@@ -519,18 +552,21 @@ module MatrixSdk
|
|
519
552
|
raise ArgumentError, 'Must be a room ID' unless room_id.room_id?
|
520
553
|
|
521
554
|
room_id = room_id.to_s
|
522
|
-
@rooms.fetch(room_id) do
|
555
|
+
ret = @rooms.fetch(room_id) do
|
523
556
|
room = Room.new(self, room_id)
|
524
557
|
@rooms[room_id] = room unless cache == :none
|
525
558
|
room
|
526
559
|
end
|
560
|
+
# Need to figure out a way to handle multiple types
|
561
|
+
ret = @rooms[room_id] = ret.to_space if ret.instance_variable_get :@room_type
|
562
|
+
ret
|
527
563
|
end
|
528
564
|
|
529
565
|
def listen_forever(timeout: 30, bad_sync_timeout: 5, sync_interval: 0, **params)
|
530
566
|
orig_bad_sync_timeout = bad_sync_timeout + 0
|
531
567
|
while @should_listen
|
532
568
|
begin
|
533
|
-
sync(params.merge(timeout: timeout))
|
569
|
+
sync(**params.merge(timeout: timeout))
|
534
570
|
|
535
571
|
bad_sync_timeout = orig_bad_sync_timeout
|
536
572
|
sleep(sync_interval) if sync_interval.positive?
|
@@ -552,7 +588,7 @@ module MatrixSdk
|
|
552
588
|
private
|
553
589
|
|
554
590
|
def post_authentication(data)
|
555
|
-
@mxid = data[:user_id]
|
591
|
+
@mxid = MXID.new data[:user_id]
|
556
592
|
@api.access_token = data[:access_token]
|
557
593
|
@api.device_id = data[:device_id]
|
558
594
|
@api.homeserver = data[:home_server]
|
@@ -566,65 +602,38 @@ module MatrixSdk
|
|
566
602
|
|
567
603
|
room = ensure_room(room_id)
|
568
604
|
room.send :put_state_event, state_event
|
569
|
-
content = state_event[:content]
|
570
|
-
case state_event[:type]
|
571
|
-
when 'm.room.name'
|
572
|
-
room.instance_variable_set '@name', content[:name]
|
573
|
-
when 'm.room.canonical_alias'
|
574
|
-
room.instance_variable_set '@canonical_alias', content[:alias]
|
575
|
-
# Also add as a regular alias
|
576
|
-
room.instance_variable_get('@aliases').concat [content[:alias]]
|
577
|
-
when 'm.room.topic'
|
578
|
-
room.instance_variable_set '@topic', content[:topic]
|
579
|
-
when 'm.room.aliases'
|
580
|
-
room.instance_variable_get('@aliases').concat content[:aliases]
|
581
|
-
when 'm.room.join_rules'
|
582
|
-
room.instance_variable_set '@join_rule', content[:join_rule].nil? ? nil : content[:join_rule].to_sym
|
583
|
-
when 'm.room.guest_access'
|
584
|
-
room.instance_variable_set '@guest_access', content[:guest_access].nil? ? nil : content[:guest_access].to_sym
|
585
|
-
when 'm.room.member'
|
586
|
-
return unless cache == :all
|
587
|
-
|
588
|
-
if content[:membership] == 'join'
|
589
|
-
room.send(:ensure_member, get_user(state_event[:state_key]).dup.tap do |u|
|
590
|
-
u.instance_variable_set :@display_name, content[:displayname]
|
591
|
-
end)
|
592
|
-
elsif %w[leave kick invite].include? content[:membership]
|
593
|
-
room.members.delete_if { |m| m.id == state_event[:state_key] }
|
594
|
-
end
|
595
|
-
end
|
596
605
|
end
|
597
606
|
|
598
607
|
def handle_sync_response(data)
|
599
|
-
data
|
608
|
+
data.dig(:presence, :events)&.each do |presence_update|
|
600
609
|
fire_presence_event(MatrixEvent.new(self, presence_update))
|
601
610
|
end
|
602
611
|
|
603
|
-
data
|
612
|
+
data.dig(:rooms, :invite)&.each do |room_id, invite|
|
604
613
|
invite[:room_id] = room_id.to_s
|
605
614
|
fire_invite_event(MatrixEvent.new(self, invite), room_id.to_s)
|
606
615
|
end
|
607
616
|
|
608
|
-
data
|
617
|
+
data.dig(:rooms, :leave)&.each do |room_id, left|
|
609
618
|
left[:room_id] = room_id.to_s
|
610
619
|
fire_leave_event(MatrixEvent.new(self, left), room_id.to_s)
|
611
620
|
end
|
612
621
|
|
613
|
-
data
|
622
|
+
data.dig(:rooms, :join)&.each do |room_id, join|
|
614
623
|
room = ensure_room(room_id)
|
615
|
-
room.instance_variable_set '@prev_batch', join
|
624
|
+
room.instance_variable_set '@prev_batch', join.dig(:timeline, :prev_batch)
|
616
625
|
room.instance_variable_set :@members_loaded, true unless sync_filter.fetch(:room, {}).fetch(:state, {}).fetch(:lazy_load_members, false)
|
617
626
|
|
618
|
-
join
|
627
|
+
join.dig(:state, :events)&.each do |event|
|
619
628
|
event[:room_id] = room_id.to_s
|
620
629
|
handle_state(room_id, event)
|
621
630
|
end
|
622
631
|
|
623
|
-
join
|
632
|
+
join.dig(:timeline, :events)&.each do |event|
|
624
633
|
event[:room_id] = room_id.to_s
|
625
634
|
# Avoid sending two identical state events if it's both in state and timeline
|
626
635
|
if event.key?(:state_key)
|
627
|
-
state_event = join.dig(:state, :events)
|
636
|
+
state_event = join.dig(:state, :events)&.find { |ev| ev[:event_id] == event[:event_id] }
|
628
637
|
|
629
638
|
handle_state(room_id, event) unless event == state_event
|
630
639
|
end
|
@@ -633,7 +642,7 @@ module MatrixSdk
|
|
633
642
|
fire_event(MatrixEvent.new(self, event), event[:type])
|
634
643
|
end
|
635
644
|
|
636
|
-
join
|
645
|
+
join.dig(:ephemeral, :events)&.each do |event|
|
637
646
|
event[:room_id] = room_id.to_s
|
638
647
|
room.send :put_ephemeral_event, event
|
639
648
|
|
@@ -641,6 +650,14 @@ module MatrixSdk
|
|
641
650
|
end
|
642
651
|
end
|
643
652
|
|
653
|
+
unless cache == :none
|
654
|
+
@rooms.each do |_id, room|
|
655
|
+
# Clean up old cache data after every sync
|
656
|
+
# TODO Run this in a thread?
|
657
|
+
room.tinycache_adapter.cleanup
|
658
|
+
end
|
659
|
+
end
|
660
|
+
|
644
661
|
nil
|
645
662
|
end
|
646
663
|
end
|
data/lib/matrix_sdk/errors.rb
CHANGED
@@ -41,9 +41,13 @@ module MatrixSdk
|
|
41
41
|
end
|
42
42
|
|
43
43
|
class MatrixNotAuthorizedError < MatrixRequestError; end
|
44
|
+
|
44
45
|
class MatrixForbiddenError < MatrixRequestError; end
|
46
|
+
|
45
47
|
class MatrixNotFoundError < MatrixRequestError; end
|
48
|
+
|
46
49
|
class MatrixConflictError < MatrixRequestError; end
|
50
|
+
|
47
51
|
class MatrixTooManyRequestsError < MatrixRequestError; end
|
48
52
|
|
49
53
|
# An error raised when errors occur in the connection layer
|
data/lib/matrix_sdk/mxid.rb
CHANGED
@@ -12,7 +12,7 @@ module MatrixSdk
|
|
12
12
|
|
13
13
|
# TODO: Community-as-a-Room / Profile-as-a-Room, in case they're going for room aliases
|
14
14
|
@sigil = identifier[0]
|
15
|
-
@localpart, @domain, @port = identifier[1
|
15
|
+
@localpart, @domain, @port = identifier[1..].split(':')
|
16
16
|
@port = @port.to_i if @port
|
17
17
|
|
18
18
|
raise ArgumentError, 'Identifier is not a valid MXID' unless valid?
|
@@ -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
|
@@ -105,5 +100,45 @@ module MatrixSdk
|
|
105
100
|
def room_alias?
|
106
101
|
type == :room_alias
|
107
102
|
end
|
103
|
+
|
104
|
+
# Converts the MXID to a matrix: URI according to MSC2312
|
105
|
+
# @param event_id [String,MXID] An event ID to append to the URI (only valid for rooms)
|
106
|
+
# @param action [String,Symbol] The action that should be requested
|
107
|
+
# @param via [Array[String]] The list of servers to use for a join
|
108
|
+
# @see https://github.com/matrix-org/matrix-doc/blob/master/proposals/2312-matrix-uri.md
|
109
|
+
def to_uri(event_id: nil, action: nil, via: nil)
|
110
|
+
uri = ''
|
111
|
+
|
112
|
+
case sigil
|
113
|
+
when '@'
|
114
|
+
raise ArgumentError, "can't provide via for user URIs" if via
|
115
|
+
raise ArgumentError, "can't provide event_id for user URIs" if event_id
|
116
|
+
|
117
|
+
uri += 'u'
|
118
|
+
when '#'
|
119
|
+
uri += 'r'
|
120
|
+
when '!'
|
121
|
+
uri += 'roomid'
|
122
|
+
else
|
123
|
+
raise ArgumentError, "this MXID can't be converted to a URI"
|
124
|
+
end
|
125
|
+
|
126
|
+
uri = "matrix:#{uri}/#{localpart}#{homeserver_suffix}"
|
127
|
+
|
128
|
+
uri += "/e/#{event_id.to_s.delete_prefix('$')}" if event_id
|
129
|
+
query = []
|
130
|
+
query << "action=#{action}" if action
|
131
|
+
[via].flatten.compact.each { |v| query << "via=#{v}" }
|
132
|
+
|
133
|
+
uri += "?#{query.join('&')}" unless query.empty?
|
134
|
+
|
135
|
+
URI(uri)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Check if two MXIDs are equal
|
139
|
+
# @return [Boolean]
|
140
|
+
def ==(other)
|
141
|
+
to_s == other.to_s
|
142
|
+
end
|
108
143
|
end
|
109
144
|
end
|