matrix_sdk 2.1.3 → 2.5.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 +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
|