matrix_sdk 2.1.0 → 2.3.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 +37 -0
- data/README.md +1 -1
- data/lib/matrix_sdk.rb +6 -1
- data/lib/matrix_sdk/api.rb +87 -45
- data/lib/matrix_sdk/client.rb +56 -42
- data/lib/matrix_sdk/errors.rb +4 -0
- data/lib/matrix_sdk/mxid.rb +9 -14
- data/lib/matrix_sdk/protocols/cs.rb +61 -37
- data/lib/matrix_sdk/protocols/msc.rb +1 -1
- data/lib/matrix_sdk/response.rb +3 -1
- data/lib/matrix_sdk/room.rb +312 -109
- data/lib/matrix_sdk/user.rb +8 -0
- data/lib/matrix_sdk/{extensions.rb → util/events.rb} +4 -86
- data/lib/matrix_sdk/util/extensions.rb +90 -0
- data/lib/matrix_sdk/util/tinycache.rb +122 -0
- data/lib/matrix_sdk/util/tinycache_adapter.rb +72 -0
- data/lib/matrix_sdk/version.rb +1 -1
- metadata +10 -8
- data/lib/matrix_sdk/application_service.rb +0 -212
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb2cd8492e977a8c63d80d3a250841111f872b45ef48a06ac610dd6c871c5704
|
4
|
+
data.tar.gz: b5932dc63938f86a4bec522f2d5736871f3a5461ad5d25581c2ba1cd79b20ab2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ed57a7d4b3296a15c244c88ca88777d6ed3f9b67a6c4cdaae017f56c6e15cf94ba0781c6831a70f7adf9c55605073c84c451b0c1b0b8bffe323015330294f19
|
7
|
+
data.tar.gz: f77aaa05a45917b80aa296b7ff73f37d60ba5fb36f29a3e753cec1a730681a428c33ccdae9f4c26648952d6a7b05f9636e7d7ffbbe8757d23d2c435378d3466b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,40 @@
|
|
1
|
+
## 2.3.0 - 2021-03-26
|
2
|
+
|
3
|
+
- Adds support for Ruby 3.0 (#15)
|
4
|
+
- Adds support for requests against the Synapse admin API
|
5
|
+
- Adds helper methods for checking and changing user power levels
|
6
|
+
- Adds a proper caching system for room data
|
7
|
+
- Fixes argument error in `#get_room_messages`
|
8
|
+
- Removes unfinished and broken AS abstraction
|
9
|
+
|
10
|
+
## 2.2.0 - 2020-11-20
|
11
|
+
|
12
|
+
- Adds direct message (1:1) room mapping to client abstraction
|
13
|
+
- Adds Api#get_room_event_context (#13)
|
14
|
+
- Improves support for JRuby
|
15
|
+
|
16
|
+
## 2.1.3 - 2020-09-18
|
17
|
+
|
18
|
+
- Adds separate state event handler as Client#on_state_event
|
19
|
+
- Changes Client sync interval to by-default run at full speed
|
20
|
+
- Fixes state events being sent twice if included in both timeline and state of a sync
|
21
|
+
- Improves error reporting of broken 200 responses
|
22
|
+
- Improves event handlers for rooms, to not depend on a specific room object instance anymore
|
23
|
+
|
24
|
+
## 2.1.2 - 2020-09-10
|
25
|
+
|
26
|
+
- Adds method for reading complete member lists for rooms, improves the CS spec adherence
|
27
|
+
- Adds test for state events
|
28
|
+
- Fixes state event handler for rooms not actually passing events
|
29
|
+
- Fixes Api#new_for_domain using a faulty URI in certain cases
|
30
|
+
|
31
|
+
## 2.1.1 - 2020-08-21
|
32
|
+
|
33
|
+
- Fixes crash if state event content is null (#11)
|
34
|
+
- Fixes an uninitialized URI constant exception when requiring only the main library file
|
35
|
+
- Fixes the Api#get_pushrules method missing an ending slash in the request URI
|
36
|
+
- Fixes discovery code for client/server connections based on domain
|
37
|
+
|
1
38
|
## 2.1.0 - 2020-05-22
|
2
39
|
|
3
40
|
- Adds unique query IDs as well as duration in API debug output, to make it easier to track long requests
|
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.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'matrix_sdk/extensions'
|
3
|
+
require 'matrix_sdk/util/extensions'
|
4
4
|
require 'matrix_sdk/version'
|
5
5
|
|
6
6
|
require 'json'
|
@@ -22,6 +22,11 @@ module MatrixSdk
|
|
22
22
|
autoload :MatrixTimeoutError, 'matrix_sdk/errors'
|
23
23
|
autoload :MatrixUnexpectedResponseError, 'matrix_sdk/errors'
|
24
24
|
|
25
|
+
module Util
|
26
|
+
autoload :Tinycache, 'matrix_sdk/util/tinycache'
|
27
|
+
autoload :TinycacheAdapter, 'matrix_sdk/util/tinycache_adapter'
|
28
|
+
end
|
29
|
+
|
25
30
|
module Protocols
|
26
31
|
autoload :AS, 'matrix_sdk/protocols/as'
|
27
32
|
autoload :CS, 'matrix_sdk/protocols/cs'
|
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
|
@@ -61,6 +62,7 @@ module MatrixSdk
|
|
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
|
65
67
|
|
66
68
|
([params.fetch(:protocols, [:CS])].flatten - protocols).each do |proto|
|
@@ -92,6 +94,8 @@ module MatrixSdk
|
|
92
94
|
uri = URI("http#{ssl ? 's' : ''}://#{domain}")
|
93
95
|
well_known = nil
|
94
96
|
target_uri = nil
|
97
|
+
logger = ::Logging.logger[self]
|
98
|
+
logger.debug "Resolving #{domain}"
|
95
99
|
|
96
100
|
if !port.nil? && !port.empty?
|
97
101
|
# If the domain is fully qualified according to Matrix (FQDN and port) then skip discovery
|
@@ -99,21 +103,30 @@ module MatrixSdk
|
|
99
103
|
elsif target == :server
|
100
104
|
# Attempt SRV record discovery
|
101
105
|
target_uri = begin
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
106
|
+
require 'resolv'
|
107
|
+
resolver = Resolv::DNS.new
|
108
|
+
srv = "_matrix._tcp.#{domain}"
|
109
|
+
logger.debug "Trying DNS #{srv}..."
|
110
|
+
d = resolver.getresource(srv, Resolv::DNS::Resource::IN::SRV)
|
111
|
+
d
|
112
|
+
rescue StandardError => e
|
113
|
+
logger.debug "DNS lookup failed with #{e.class}: #{e.message}"
|
114
|
+
nil
|
115
|
+
end
|
108
116
|
|
109
117
|
if target_uri.nil?
|
110
118
|
# Attempt .well-known discovery for server-to-server
|
111
119
|
well_known = begin
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
120
|
+
wk_uri = URI("https://#{domain}/.well-known/matrix/server")
|
121
|
+
logger.debug "Trying #{wk_uri}..."
|
122
|
+
data = Net::HTTP.start(wk_uri.host, wk_uri.port, use_ssl: true, open_timeout: 5, read_timeout: 5, write_timeout: 5) do |http|
|
123
|
+
http.get(wk_uri.path).body
|
124
|
+
end
|
125
|
+
JSON.parse(data)
|
126
|
+
rescue StandardError => e
|
127
|
+
logger.debug "Well-known failed with #{e.class}: #{e.message}"
|
128
|
+
nil
|
129
|
+
end
|
117
130
|
|
118
131
|
target_uri = well_known['m.server'] if well_known&.key?('m.server')
|
119
132
|
else
|
@@ -122,11 +135,16 @@ module MatrixSdk
|
|
122
135
|
elsif %i[client identity].include? target
|
123
136
|
# Attempt .well-known discovery
|
124
137
|
well_known = begin
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
138
|
+
wk_uri = URI("https://#{domain}/.well-known/matrix/client")
|
139
|
+
logger.debug "Trying #{wk_uri}..."
|
140
|
+
data = Net::HTTP.start(wk_uri.host, wk_uri.port, use_ssl: true, open_timeout: 5, read_timeout: 5, write_timeout: 5) do |http|
|
141
|
+
http.get(wk_uri.path).body
|
142
|
+
end
|
143
|
+
JSON.parse(data)
|
144
|
+
rescue StandardError => e
|
145
|
+
logger.debug "Well-known failed with #{e.class}: #{e.message}"
|
146
|
+
nil
|
147
|
+
end
|
130
148
|
|
131
149
|
if well_known
|
132
150
|
key = 'm.homeserver'
|
@@ -138,17 +156,20 @@ module MatrixSdk
|
|
138
156
|
end
|
139
157
|
end
|
140
158
|
end
|
159
|
+
logger.debug "Using #{target_uri.inspect}"
|
141
160
|
|
142
161
|
# Fall back to direct domain connection
|
143
162
|
target_uri ||= URI("https://#{domain}:8448")
|
144
163
|
|
145
164
|
params[:well_known] = well_known if keep_wellknown
|
146
165
|
|
147
|
-
new(
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
166
|
+
new(
|
167
|
+
uri,
|
168
|
+
**params.merge(
|
169
|
+
address: target_uri.host,
|
170
|
+
port: target_uri.port
|
171
|
+
)
|
172
|
+
)
|
152
173
|
end
|
153
174
|
|
154
175
|
# Get a list of enabled protocols on the API client
|
@@ -251,23 +272,6 @@ module MatrixSdk
|
|
251
272
|
u.query = [u.query, URI.encode_www_form(options.fetch(:query))].flatten.compact.join('&') if options[:query]
|
252
273
|
u.query = nil if u.query.nil? || u.query.empty?
|
253
274
|
end
|
254
|
-
request = Net::HTTP.const_get(method.to_s.capitalize.to_sym).new url.request_uri
|
255
|
-
request.body = options[:body] if options.key? :body
|
256
|
-
request.body = request.body.to_json if options.key?(:body) && !request.body.is_a?(String)
|
257
|
-
request.body_stream = options[:body_stream] if options.key? :body_stream
|
258
|
-
|
259
|
-
global_headers.each { |h, v| request[h] = v }
|
260
|
-
if request.body || request.body_stream
|
261
|
-
request.content_type = 'application/json'
|
262
|
-
request.content_length = (request.body || request.body_stream).size
|
263
|
-
end
|
264
|
-
|
265
|
-
request['authorization'] = "Bearer #{access_token}" if access_token && !options.fetch(:skip_auth, false)
|
266
|
-
if options.key? :headers
|
267
|
-
options[:headers].each do |h, v|
|
268
|
-
request[h.to_s.downcase] = v
|
269
|
-
end
|
270
|
-
end
|
271
275
|
|
272
276
|
failures = 0
|
273
277
|
loop do
|
@@ -275,10 +279,11 @@ module MatrixSdk
|
|
275
279
|
|
276
280
|
req_id = ('A'..'Z').to_a.sample(4).join
|
277
281
|
|
278
|
-
|
282
|
+
req_obj = construct_request(url: url, method: method, **options)
|
283
|
+
print_http(req_obj, id: req_id)
|
279
284
|
begin
|
280
285
|
dur_start = Time.now
|
281
|
-
response = http.request
|
286
|
+
response = http.request req_obj
|
282
287
|
dur_end = Time.now
|
283
288
|
duration = dur_end - dur_start
|
284
289
|
rescue EOFError
|
@@ -287,7 +292,12 @@ module MatrixSdk
|
|
287
292
|
end
|
288
293
|
print_http(response, duration: duration, id: req_id)
|
289
294
|
|
290
|
-
|
295
|
+
begin
|
296
|
+
data = JSON.parse(response.body, symbolize_names: true)
|
297
|
+
rescue JSON::JSONError => e
|
298
|
+
logger.debug "#{e.class} error when parsing response. #{e}"
|
299
|
+
data = nil
|
300
|
+
end
|
291
301
|
|
292
302
|
if response.is_a? Net::HTTPTooManyRequests
|
293
303
|
raise MatrixRequestError.new_by_code(data, response.code) unless autoretry
|
@@ -298,7 +308,13 @@ module MatrixSdk
|
|
298
308
|
next
|
299
309
|
end
|
300
310
|
|
301
|
-
|
311
|
+
if response.is_a? Net::HTTPSuccess
|
312
|
+
unless data
|
313
|
+
logger.error "Received non-parsable data in 200 response; #{response.body.inspect}"
|
314
|
+
raise MatrixConnectionError, response
|
315
|
+
end
|
316
|
+
return MatrixSdk::Response.new self, data
|
317
|
+
end
|
302
318
|
raise MatrixRequestError.new_by_code(data, response.code) if data
|
303
319
|
|
304
320
|
raise MatrixConnectionError.class_by_code(response.code), response
|
@@ -316,14 +332,38 @@ module MatrixSdk
|
|
316
332
|
|
317
333
|
private
|
318
334
|
|
335
|
+
def construct_request(method:, url:, **options)
|
336
|
+
request = Net::HTTP.const_get(method.to_s.capitalize.to_sym).new url.request_uri
|
337
|
+
|
338
|
+
# FIXME: Handle bodies better, avoid duplicating work
|
339
|
+
request.body = options[:body] if options.key? :body
|
340
|
+
request.body = request.body.to_json if options.key?(:body) && !request.body.is_a?(String)
|
341
|
+
request.body_stream = options[:body_stream] if options.key? :body_stream
|
342
|
+
|
343
|
+
global_headers.each { |h, v| request[h] = v }
|
344
|
+
if request.body || request.body_stream
|
345
|
+
request.content_type = 'application/json'
|
346
|
+
request.content_length = (request.body || request.body_stream).size
|
347
|
+
end
|
348
|
+
|
349
|
+
request['authorization'] = "Bearer #{access_token}" if access_token && !options.fetch(:skip_auth, false)
|
350
|
+
if options.key? :headers
|
351
|
+
options[:headers].each do |h, v|
|
352
|
+
request[h.to_s.downcase] = v
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
request
|
357
|
+
end
|
358
|
+
|
319
359
|
def print_http(http, body: true, duration: nil, id: nil)
|
320
360
|
return unless logger.debug?
|
321
361
|
|
322
362
|
if http.is_a? Net::HTTPRequest
|
323
|
-
dir = "#{id ? id
|
363
|
+
dir = "#{id ? "#{id} : " : nil}>"
|
324
364
|
logger.debug "#{dir} Sending a #{http.method} request to `#{http.path}`:"
|
325
365
|
else
|
326
|
-
dir = "#{id ? id
|
366
|
+
dir = "#{id ? "#{id} : " : nil}<"
|
327
367
|
logger.debug "#{dir} Received a #{http.code} #{http.message} response:#{duration ? " [#{(duration * 1000).to_i}ms]" : nil}"
|
328
368
|
end
|
329
369
|
http.to_hash.map { |k, v| "#{k}: #{k == 'authorization' ? '[ REDACTED ]' : v.join(', ')}" }.each do |h|
|
@@ -332,7 +372,7 @@ module MatrixSdk
|
|
332
372
|
logger.debug dir
|
333
373
|
if body
|
334
374
|
clean_body = JSON.parse(http.body) rescue nil if http.body
|
335
|
-
clean_body.
|
375
|
+
clean_body.each_key { |k| clean_body[k] = '[ REDACTED ]' if %w[password access_token].include?(k) }.to_json if clean_body.is_a? Hash
|
336
376
|
clean_body = clean_body.to_s if clean_body
|
337
377
|
logger.debug "#{dir} #{clean_body.length < 200 ? clean_body : clean_body.slice(0..200) + "... [truncated, #{clean_body.length} Bytes]"}" if clean_body
|
338
378
|
end
|
@@ -341,6 +381,8 @@ module MatrixSdk
|
|
341
381
|
end
|
342
382
|
|
343
383
|
def api_to_path(api)
|
384
|
+
return "/_synapse/#{api.to_s.split('_').join('/')}" if @synapse && api.to_s.start_with?('admin_')
|
385
|
+
|
344
386
|
# TODO: <api>_current / <api>_latest
|
345
387
|
"/_matrix/#{api.to_s.split('_').join('/')}"
|
346
388
|
end
|
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'
|
@@ -23,7 +24,7 @@ module MatrixSdk
|
|
23
24
|
attr_reader :api, :next_batch
|
24
25
|
attr_accessor :cache, :sync_filter
|
25
26
|
|
26
|
-
events :error, :event, :presence_event, :invite_event, :leave_event, :ephemeral_event
|
27
|
+
events :error, :event, :presence_event, :invite_event, :leave_event, :ephemeral_event, :state_event
|
27
28
|
ignore_inspect :api,
|
28
29
|
:on_event, :on_presence_event, :on_invite_event, :on_leave_event, :on_ephemeral_event
|
29
30
|
|
@@ -44,7 +45,7 @@ module MatrixSdk
|
|
44
45
|
# @see #initialize
|
45
46
|
def self.new_for_domain(domain, **params)
|
46
47
|
api = MatrixSdk::Api.new_for_domain(domain, keep_wellknown: true)
|
47
|
-
return new(api, params) unless api.well_known
|
48
|
+
return new(api, params) unless api.well_known&.key?('m.identity_server')
|
48
49
|
|
49
50
|
identity_server = MatrixSdk::Api.new(api.well_known['m.identity_server']['base_url'], protocols: %i[IS])
|
50
51
|
new(api, params.merge(identity_server: identity_server))
|
@@ -67,11 +68,9 @@ 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
|
-
@rooms = {}
|
74
|
-
@users = {}
|
75
74
|
@cache = client_cache
|
76
75
|
@identity_server = nil
|
77
76
|
|
@@ -79,7 +78,6 @@ module MatrixSdk
|
|
79
78
|
@sync_thread = nil
|
80
79
|
@sync_filter = { room: { timeline: { limit: params.fetch(:sync_filter_limit, 20) }, state: { lazy_load_members: true } } }
|
81
80
|
|
82
|
-
@should_listen = false
|
83
81
|
@next_batch = nil
|
84
82
|
|
85
83
|
@bad_sync_timeout_limit = 60 * 60
|
@@ -88,6 +86,11 @@ module MatrixSdk
|
|
88
86
|
instance_variable_set("@#{k}", v) if instance_variable_defined? "@#{k}"
|
89
87
|
end
|
90
88
|
|
89
|
+
@rooms = {}
|
90
|
+
@room_handlers = {}
|
91
|
+
@users = {}
|
92
|
+
@should_listen = false
|
93
|
+
|
91
94
|
raise ArgumentError, 'Cache value must be one of of [:all, :some, :none]' unless %i[all some none].include? @cache
|
92
95
|
|
93
96
|
return unless params[:user_id]
|
@@ -154,6 +157,27 @@ module MatrixSdk
|
|
154
157
|
rooms
|
155
158
|
end
|
156
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
|
+
Hash[api.get_account_data(mxid, 'm.direct').map do |mxid, rooms|
|
165
|
+
[mxid.to_s, rooms]
|
166
|
+
end]
|
167
|
+
end
|
168
|
+
|
169
|
+
# Gets a direct message room for the given user if one exists
|
170
|
+
#
|
171
|
+
# @note Will return the oldest room if multiple exist
|
172
|
+
# @return [Room,nil] A direct message room if one exists
|
173
|
+
def direct_room(mxid)
|
174
|
+
mxid = MatrixSdk::MXID.new mxid.to_s unless mxid.is_a? MatrixSdk::MXID
|
175
|
+
raise ArgumentError, 'Must be a valid user ID' unless mxid.user?
|
176
|
+
|
177
|
+
room_id = direct_rooms[mxid.to_s]&.first
|
178
|
+
ensure_room room_id if room_id
|
179
|
+
end
|
180
|
+
|
157
181
|
# Gets a list of all relevant rooms, either the ones currently handled by
|
158
182
|
# the client, or the list of currently joined ones if no rooms are handled
|
159
183
|
#
|
@@ -337,13 +361,13 @@ module MatrixSdk
|
|
337
361
|
# @return [Room] The resulting room
|
338
362
|
# @see Protocols::CS#create_room
|
339
363
|
def create_room(room_alias = nil, **params)
|
340
|
-
data = api.create_room(params.merge(room_alias: room_alias))
|
364
|
+
data = api.create_room(**params.merge(room_alias: room_alias))
|
341
365
|
ensure_room(data.room_id)
|
342
366
|
end
|
343
367
|
|
344
368
|
# Joins an already created room
|
345
369
|
#
|
346
|
-
# @param room_id_or_alias [String,MXID] A room alias (#room:
|
370
|
+
# @param room_id_or_alias [String,MXID] A room alias (#room:example.com) or a room ID (!id:example.com)
|
347
371
|
# @param server_name [Array[String]] A list of servers to attempt the join through, required for IDs
|
348
372
|
# @return [Room] The resulting room
|
349
373
|
# @see Protocols::CS#join_room
|
@@ -431,10 +455,11 @@ module MatrixSdk
|
|
431
455
|
errors = 0
|
432
456
|
thread, cancel_token = api.msc2108_sync_sse(params) do |data, event:, id:|
|
433
457
|
@next_batch = id if id
|
434
|
-
|
458
|
+
case event.to_sym
|
459
|
+
when :sync
|
435
460
|
handle_sync_response(data)
|
436
461
|
errors = 0
|
437
|
-
|
462
|
+
when :sync_error
|
438
463
|
logger.error "SSE Sync error received; #{data.type}: #{data.message}"
|
439
464
|
errors += 1
|
440
465
|
|
@@ -445,7 +470,7 @@ module MatrixSdk
|
|
445
470
|
|
446
471
|
@should_listen = cancel_token
|
447
472
|
else
|
448
|
-
thread = Thread.new { listen_forever(params) }
|
473
|
+
thread = Thread.new { listen_forever(**params) }
|
449
474
|
end
|
450
475
|
@sync_thread = thread
|
451
476
|
thread.run
|
@@ -494,7 +519,7 @@ module MatrixSdk
|
|
494
519
|
attempts = 0
|
495
520
|
data = loop do
|
496
521
|
begin
|
497
|
-
break api.sync extra_params
|
522
|
+
break api.sync **extra_params
|
498
523
|
rescue MatrixSdk::MatrixTimeoutError => e
|
499
524
|
raise e if (attempts += 1) >= params.fetch(:allow_sync_retry, 0)
|
500
525
|
end
|
@@ -524,11 +549,11 @@ module MatrixSdk
|
|
524
549
|
end
|
525
550
|
end
|
526
551
|
|
527
|
-
def listen_forever(timeout: 30, bad_sync_timeout: 5, sync_interval:
|
552
|
+
def listen_forever(timeout: 30, bad_sync_timeout: 5, sync_interval: 0, **params)
|
528
553
|
orig_bad_sync_timeout = bad_sync_timeout + 0
|
529
554
|
while @should_listen
|
530
555
|
begin
|
531
|
-
sync(params.merge(timeout: timeout))
|
556
|
+
sync(**params.merge(timeout: timeout))
|
532
557
|
|
533
558
|
bad_sync_timeout = orig_bad_sync_timeout
|
534
559
|
sleep(sync_interval) if sync_interval.positive?
|
@@ -560,34 +585,10 @@ module MatrixSdk
|
|
560
585
|
def handle_state(room_id, state_event)
|
561
586
|
return unless state_event.key? :type
|
562
587
|
|
588
|
+
on_state_event.fire(MatrixEvent.new(self, state_event), state_event[:type])
|
589
|
+
|
563
590
|
room = ensure_room(room_id)
|
564
|
-
|
565
|
-
case state_event[:type]
|
566
|
-
when 'm.room.name'
|
567
|
-
room.instance_variable_set '@name', content[:name]
|
568
|
-
when 'm.room.canonical_alias'
|
569
|
-
room.instance_variable_set '@canonical_alias', content[:alias]
|
570
|
-
# Also add as a regular alias
|
571
|
-
room.instance_variable_get('@aliases').concat [content[:alias]]
|
572
|
-
when 'm.room.topic'
|
573
|
-
room.instance_variable_set '@topic', content[:topic]
|
574
|
-
when 'm.room.aliases'
|
575
|
-
room.instance_variable_get('@aliases').concat content[:aliases]
|
576
|
-
when 'm.room.join_rules'
|
577
|
-
room.instance_variable_set '@join_rule', content[:join_rule].to_sym
|
578
|
-
when 'm.room.guest_access'
|
579
|
-
room.instance_variable_set '@guest_access', content[:guest_access].to_sym
|
580
|
-
when 'm.room.member'
|
581
|
-
return unless cache == :all
|
582
|
-
|
583
|
-
if content[:membership] == 'join'
|
584
|
-
room.send(:ensure_member, get_user(state_event[:state_key]).dup.tap do |u|
|
585
|
-
u.instance_variable_set :@display_name, content[:displayname]
|
586
|
-
end)
|
587
|
-
elsif %w[leave kick invite].include? content[:membership]
|
588
|
-
room.members.delete_if { |m| m.id == state_event[:state_key] }
|
589
|
-
end
|
590
|
-
end
|
591
|
+
room.send :put_state_event, state_event
|
591
592
|
end
|
592
593
|
|
593
594
|
def handle_sync_response(data)
|
@@ -617,7 +618,12 @@ module MatrixSdk
|
|
617
618
|
|
618
619
|
join[:timeline][:events].each do |event|
|
619
620
|
event[:room_id] = room_id.to_s
|
620
|
-
|
621
|
+
# Avoid sending two identical state events if it's both in state and timeline
|
622
|
+
if event.key?(:state_key)
|
623
|
+
state_event = join.dig(:state, :events).find { |ev| ev[:event_id] == event[:event_id] }
|
624
|
+
|
625
|
+
handle_state(room_id, event) unless event == state_event
|
626
|
+
end
|
621
627
|
room.send :put_event, event
|
622
628
|
|
623
629
|
fire_event(MatrixEvent.new(self, event), event[:type])
|
@@ -631,6 +637,14 @@ module MatrixSdk
|
|
631
637
|
end
|
632
638
|
end
|
633
639
|
|
640
|
+
unless cache == :none
|
641
|
+
@rooms.each do |_id, room|
|
642
|
+
# Clean up old cache data after every sync
|
643
|
+
# TODO Run this in a thread?
|
644
|
+
room.tinycache_adapter.cleanup
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
634
648
|
nil
|
635
649
|
end
|
636
650
|
end
|