matrix_sdk 1.5.0 → 2.0.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 +18 -0
- data/lib/matrix_sdk/api.rb +35 -2
- data/lib/matrix_sdk/client.rb +222 -22
- data/lib/matrix_sdk/extensions.rb +1 -0
- data/lib/matrix_sdk/mxid.rb +24 -2
- data/lib/matrix_sdk/protocols/cs.rb +728 -52
- data/lib/matrix_sdk/response.rb +11 -0
- data/lib/matrix_sdk/room.rb +110 -13
- data/lib/matrix_sdk/user.rb +75 -8
- data/lib/matrix_sdk/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e0e5819346e56fd4eac1564434e88399500adefe0def16bc706a25ec7a254b2
|
4
|
+
data.tar.gz: 2d74cd2d5203f5431396b03717c4302f9a0c7816c47eaa969e2395ab2eb46586
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7eb8ef8277b0bda1191915e5be4dcf93856cd876f611b77974b8dc88e5e230ba5c3300995157f9717a4b00d1a7cba7f7a618844cc436ad0b6a3ea5865367049d
|
7
|
+
data.tar.gz: bd888c36cf3a082360dbecc408c0a67e16ddb337a721105be7abf3a9662d81bfa564a1093a64d1f934d484af6a22a36e5b91bafde70f02a882e6d092e81d5459
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 2.0.0 - 2020-02-14
|
2
|
+
|
3
|
+
**NB**, this release includes backwards-incompatible changes;
|
4
|
+
- Changes room state lookup to separate specific state lookups from full state retrieval.
|
5
|
+
This will require changes in client code where `#get_room_state` is called to retrieve
|
6
|
+
all state, as it now requires a state key. For retrieving full room state,
|
7
|
+
`#get_room_state_all` is now the method to use.
|
8
|
+
- Changes some advanced parameters to named parameters, ensure your code is updated if it makes use of them
|
9
|
+
- Fixes SSL verification to actually verify certs (#9)
|
10
|
+
|
11
|
+
- Adds multiple CS API endpoints
|
12
|
+
- Adds `:room_id` key to all room events
|
13
|
+
- Adds `:self` as a valid option to the client abstraction's `#get_user` method
|
14
|
+
- Separates homeserver part stringification for MXIDs
|
15
|
+
- Exposes some previously private client abstraction methods (`#ensure_room`, `#next_batch`) for easier bot usage
|
16
|
+
- Changes room abstraction member lookups to use `#get_room_joined_members`, reducing transferred data amounts
|
17
|
+
- Fixes debug print of methods that return arrays (e.g. CS `/room/{id}/state`)
|
18
|
+
|
1
19
|
## 1.5.0 - 2019-10-25
|
2
20
|
|
3
21
|
- Adds error event to the client abstraction, for handling errors in the background listener
|
data/lib/matrix_sdk/api.rb
CHANGED
@@ -98,6 +98,7 @@ module MatrixSdk
|
|
98
98
|
target_uri = nil
|
99
99
|
|
100
100
|
if !port.nil? && !port.empty?
|
101
|
+
# If the domain is fully qualified according to Matrix (FQDN and port) then skip discovery
|
101
102
|
target_uri = URI("https://#{domain}:#{port}")
|
102
103
|
elsif target == :server
|
103
104
|
# Attempt SRV record discovery
|
@@ -110,6 +111,7 @@ module MatrixSdk
|
|
110
111
|
end
|
111
112
|
|
112
113
|
if target_uri.nil?
|
114
|
+
# Attempt .well-known discovery for server-to-server
|
113
115
|
well_known = begin
|
114
116
|
data = Net::HTTP.get("https://#{domain}/.well-known/matrix/server")
|
115
117
|
JSON.parse(data)
|
@@ -153,6 +155,14 @@ module MatrixSdk
|
|
153
155
|
))
|
154
156
|
end
|
155
157
|
|
158
|
+
# Check if a protocol is enabled on the API connection
|
159
|
+
#
|
160
|
+
# @example Checking for identity server API support
|
161
|
+
# api.protocol? :IS
|
162
|
+
# # => false
|
163
|
+
#
|
164
|
+
# @param protocol [Symbol] The protocol to check
|
165
|
+
# @return [Boolean] Is the protocol enabled
|
156
166
|
def protocol?(protocol)
|
157
167
|
protocols.include? protocol
|
158
168
|
end
|
@@ -201,6 +211,28 @@ module MatrixSdk
|
|
201
211
|
@proxy_uri = proxy_uri
|
202
212
|
end
|
203
213
|
|
214
|
+
# Perform a raw Matrix API request
|
215
|
+
#
|
216
|
+
# @example Simple API query
|
217
|
+
# api.request(:get, :client_r0, '/account/whoami')
|
218
|
+
# # => { :user_id => "@alice:matrix.org" }
|
219
|
+
#
|
220
|
+
# @example Advanced API request
|
221
|
+
# api.request(:post,
|
222
|
+
# :media_r0,
|
223
|
+
# '/upload',
|
224
|
+
# body_stream: open('./file'),
|
225
|
+
# headers: { 'content-type' => 'image/png' })
|
226
|
+
# # => { :content_uri => "mxc://example.com/AQwafuaFswefuhsfAFAgsw" }
|
227
|
+
#
|
228
|
+
# @param method [Symbol] The method to use, can be any of the ones under Net::HTTP
|
229
|
+
# @param api [Symbol] The API symbol to use, :client_r0 is the current CS one
|
230
|
+
# @param path [String] The API path to call, this is the part that comes after the API definition in the spec
|
231
|
+
# @param options [Hash] Additional options to pass along to the request
|
232
|
+
# @option options [Hash] :query Query parameters to set on the URL
|
233
|
+
# @option options [Hash,String] :body The body to attach to the request, will be JSON-encoded if sent as a hash
|
234
|
+
# @option options [IO] :body_stream A body stream to attach to the request
|
235
|
+
# @option options [Hash] :headers Additional headers to set on the request
|
204
236
|
def request(method, api, path, **options)
|
205
237
|
url = homeserver.dup.tap do |u|
|
206
238
|
u.path = api_to_path(api) + path
|
@@ -272,7 +304,8 @@ module MatrixSdk
|
|
272
304
|
end
|
273
305
|
logger.debug dir
|
274
306
|
clean_body = JSON.parse(http.body) rescue nil if http.body
|
275
|
-
clean_body.keys.each { |k| clean_body[k] = '[ REDACTED ]' if %w[password access_token].include?(k) }.to_json if clean_body
|
307
|
+
clean_body.keys.each { |k| clean_body[k] = '[ REDACTED ]' if %w[password access_token].include?(k) }.to_json if clean_body.is_a? Hash
|
308
|
+
clean_body = clean_body.to_s if clean_body
|
276
309
|
logger.debug "#{dir} #{clean_body.length < 200 ? clean_body : clean_body.slice(0..200) + "... [truncated, #{clean_body.length} Bytes]"}" if clean_body
|
277
310
|
rescue StandardError => e
|
278
311
|
logger.warn "#{e.class} occured while printing request debug; #{e.message}\n#{e.backtrace.join "\n"}"
|
@@ -303,7 +336,7 @@ module MatrixSdk
|
|
303
336
|
@http.open_timeout = open_timeout
|
304
337
|
@http.read_timeout = read_timeout
|
305
338
|
@http.use_ssl = homeserver.scheme == 'https'
|
306
|
-
@http.verify_mode = validate_certificate ? ::OpenSSL::SSL::
|
339
|
+
@http.verify_mode = validate_certificate ? ::OpenSSL::SSL::VERIFY_PEER : ::OpenSSL::SSL::VERIFY_NONE
|
307
340
|
@http.start
|
308
341
|
@http
|
309
342
|
end
|
data/lib/matrix_sdk/client.rb
CHANGED
@@ -11,7 +11,16 @@ module MatrixSdk
|
|
11
11
|
include MatrixSdk::Logging
|
12
12
|
extend Forwardable
|
13
13
|
|
14
|
-
|
14
|
+
# @!attribute api [r] The underlying API connection
|
15
|
+
# @return [Api] The underlying API connection
|
16
|
+
# @!attribute next_batch [r] The batch token for a running sync
|
17
|
+
# @return [String] The opaque batch token
|
18
|
+
# @!attribute cache [rw] The cache level
|
19
|
+
# @return [:all,:some,:none] The level of caching to do
|
20
|
+
# @!attribute sync_filter [rw] The global sync filter
|
21
|
+
# @return [Hash,String] A filter definition, either as defined by the
|
22
|
+
# Matrix spec, or as an identifier returned by a filter creation request
|
23
|
+
attr_reader :api, :next_batch
|
15
24
|
attr_accessor :cache, :sync_filter
|
16
25
|
|
17
26
|
events :error, :event, :presence_event, :invite_event, :leave_event, :ephemeral_event
|
@@ -22,6 +31,17 @@ module MatrixSdk
|
|
22
31
|
:access_token, :access_token=, :device_id, :device_id=, :homeserver, :homeserver=,
|
23
32
|
:validate_certificate, :validate_certificate=
|
24
33
|
|
34
|
+
# Create a new client instance from only a Matrix HS domain
|
35
|
+
#
|
36
|
+
# This will use the well-known delegation lookup to find the correct client URL
|
37
|
+
#
|
38
|
+
# @note This method will not verify that the created client has a valid connection,
|
39
|
+
# it will only perform the necessary lookups to build a connection URL.
|
40
|
+
# @return [Client] The new client instance
|
41
|
+
# @param domain [String] The domain name to look up
|
42
|
+
# @param params [Hash] Additional parameters to pass along to {Api.new_for_domain} as well as {initialize}
|
43
|
+
# @see Api.new_for_domain
|
44
|
+
# @see #initialize
|
25
45
|
def self.new_for_domain(domain, **params)
|
26
46
|
api = MatrixSdk::Api.new_for_domain(domain, keep_wellknown: true)
|
27
47
|
return new(api, params) unless api.well_known.key? 'm.identity_server'
|
@@ -53,7 +73,7 @@ module MatrixSdk
|
|
53
73
|
@rooms = {}
|
54
74
|
@users = {}
|
55
75
|
@cache = client_cache
|
56
|
-
@identity_server =
|
76
|
+
@identity_server = nil
|
57
77
|
|
58
78
|
@sync_token = nil
|
59
79
|
@sync_thread = nil
|
@@ -75,22 +95,42 @@ module MatrixSdk
|
|
75
95
|
@mxid = params[:user_id]
|
76
96
|
end
|
77
97
|
|
98
|
+
# Gets the currently logged in user's MXID
|
99
|
+
#
|
100
|
+
# @return [MXID] The MXID of the current user
|
78
101
|
def mxid
|
79
102
|
@mxid ||= begin
|
80
|
-
api.whoami?[:user_id] if api&.access_token
|
103
|
+
MXID.new api.whoami?[:user_id] if api&.access_token
|
81
104
|
end
|
82
105
|
end
|
83
106
|
|
84
|
-
|
85
|
-
id = MXID.new id.to_s unless id.is_a? MXID
|
86
|
-
raise ArgumentError, 'Must be a User ID' unless id.user?
|
107
|
+
alias user_id mxid
|
87
108
|
|
88
|
-
|
109
|
+
# Gets the current user presence status object
|
110
|
+
#
|
111
|
+
# @return [Response] The user presence
|
112
|
+
# @see User#presence
|
113
|
+
# @see Protocols::CS#get_presence_status
|
114
|
+
def presence
|
115
|
+
api.get_presence_status(mxid).tap { |h| h.delete :user_id }
|
89
116
|
end
|
90
117
|
|
91
|
-
|
92
|
-
|
118
|
+
# Sets the current user's presence status
|
119
|
+
#
|
120
|
+
# @param status [:online,:offline,:unavailable] The new status to use
|
121
|
+
# @param message [String] A custom status message to set
|
122
|
+
# @see User#presence=
|
123
|
+
# @see Protocols::CS#set_presence_status
|
124
|
+
def set_presence(status, message: nil)
|
125
|
+
raise ArgumentError, 'Presence must be one of :online, :offline, :unavailable' unless %i[online offline unavailable].include?(status)
|
126
|
+
|
127
|
+
api.set_presence_status(mxid, status, message: message)
|
128
|
+
end
|
93
129
|
|
130
|
+
# Gets a list of all the public rooms on the connected HS
|
131
|
+
#
|
132
|
+
# @note This will try to list all public rooms on the HS, and may take a while on larger instances
|
133
|
+
# @return [Array[Room]] The public rooms
|
94
134
|
def public_rooms
|
95
135
|
rooms = []
|
96
136
|
since = nil
|
@@ -114,6 +154,12 @@ module MatrixSdk
|
|
114
154
|
rooms
|
115
155
|
end
|
116
156
|
|
157
|
+
# Gets a list of all relevant rooms, either the ones currently handled by
|
158
|
+
# the client, or the list of currently joined ones if no rooms are handled
|
159
|
+
#
|
160
|
+
# @return [Array[Room]] All the currently handled rooms
|
161
|
+
# @note This will always return the empty array if the cache level is set
|
162
|
+
# to :none
|
117
163
|
def rooms
|
118
164
|
if @rooms.empty? && cache != :none
|
119
165
|
api.get_joined_rooms.joined_rooms.each do |id|
|
@@ -124,6 +170,11 @@ module MatrixSdk
|
|
124
170
|
@rooms.values
|
125
171
|
end
|
126
172
|
|
173
|
+
# Refresh the list of currently handled rooms, replacing it with the user's
|
174
|
+
# currently joined rooms.
|
175
|
+
#
|
176
|
+
# @note This will be a no-op if the cache level is set to :none
|
177
|
+
# @return [Boolean] If the refresh succeeds
|
127
178
|
def reload_rooms!
|
128
179
|
return true if cache == :none
|
129
180
|
|
@@ -137,12 +188,25 @@ module MatrixSdk
|
|
137
188
|
end
|
138
189
|
alias refresh_rooms! reload_rooms!
|
139
190
|
|
191
|
+
# Register - and log in - on the connected HS as a guest
|
192
|
+
#
|
193
|
+
# @note This feature is not commonly supported by many HSes
|
140
194
|
def register_as_guest
|
141
195
|
data = api.register(kind: :guest)
|
142
196
|
post_authentication(data)
|
143
197
|
end
|
144
198
|
|
145
|
-
|
199
|
+
# Register a new user account on the connected HS
|
200
|
+
#
|
201
|
+
# This will also trigger an initial sync unless no_sync is set
|
202
|
+
#
|
203
|
+
# @note This method will currently always use auth type 'm.login.dummy'
|
204
|
+
# @param username [String] The new user's name
|
205
|
+
# @param password [String] The new user's password
|
206
|
+
# @param params [Hash] Additional options
|
207
|
+
# @option params [Boolean] :no_sync Skip the initial sync on registering
|
208
|
+
# @option params [Boolean] :allow_sync_retry Allow sync to retry on failure
|
209
|
+
def register_with_password(username, password, **params)
|
146
210
|
username = username.to_s unless username.is_a?(String)
|
147
211
|
password = password.to_s unless password.is_a?(String)
|
148
212
|
|
@@ -154,10 +218,21 @@ module MatrixSdk
|
|
154
218
|
|
155
219
|
return if params[:no_sync]
|
156
220
|
|
157
|
-
sync full_state:
|
221
|
+
sync full_state: true,
|
158
222
|
allow_sync_retry: params.fetch(:allow_sync_retry, nil)
|
159
223
|
end
|
160
224
|
|
225
|
+
# Logs in as a user on the connected HS
|
226
|
+
#
|
227
|
+
# This will also trigger an initial sync unless no_sync is set
|
228
|
+
#
|
229
|
+
# @param username [String] The username of the user
|
230
|
+
# @param password [String] The password of the user
|
231
|
+
# @param sync_timeout [Numeric] The timeout of the initial sync on login
|
232
|
+
# @param full_state [Boolean] Should the initial sync retrieve full state
|
233
|
+
# @param params [Hash] Additional options
|
234
|
+
# @option params [Boolean] :no_sync Skip the initial sync on registering
|
235
|
+
# @option params [Boolean] :allow_sync_retry Allow sync to retry on failure
|
161
236
|
def login(username, password, sync_timeout: 15, full_state: false, **params)
|
162
237
|
username = username.to_s unless username.is_a?(String)
|
163
238
|
password = password.to_s unless password.is_a?(String)
|
@@ -175,6 +250,17 @@ module MatrixSdk
|
|
175
250
|
allow_sync_retry: params.fetch(:allow_sync_retry, nil)
|
176
251
|
end
|
177
252
|
|
253
|
+
# Logs in as a user on the connected HS
|
254
|
+
#
|
255
|
+
# This will also trigger an initial sync unless no_sync is set
|
256
|
+
#
|
257
|
+
# @param username [String] The username of the user
|
258
|
+
# @param token [String] The token to log in with
|
259
|
+
# @param sync_timeout [Numeric] The timeout of the initial sync on login
|
260
|
+
# @param full_state [Boolean] Should the initial sync retrieve full state
|
261
|
+
# @param params [Hash] Additional options
|
262
|
+
# @option params [Boolean] :no_sync Skip the initial sync on registering
|
263
|
+
# @option params [Boolean] :allow_sync_retry Allow sync to retry on failure
|
178
264
|
def login_with_token(username, token, sync_timeout: 15, full_state: false, **params)
|
179
265
|
username = username.to_s unless username.is_a?(String)
|
180
266
|
token = token.to_s unless token.is_a?(String)
|
@@ -192,30 +278,90 @@ module MatrixSdk
|
|
192
278
|
allow_sync_retry: params.fetch(:allow_sync_retry, nil)
|
193
279
|
end
|
194
280
|
|
281
|
+
# Logs out of the current session
|
195
282
|
def logout
|
196
283
|
api.logout
|
197
284
|
@api.access_token = nil
|
198
285
|
@mxid = nil
|
199
286
|
end
|
200
287
|
|
288
|
+
# Check if there's a currently logged in session
|
289
|
+
#
|
290
|
+
# @note This will not check if the session is valid, only if it exists
|
291
|
+
# @return [Boolean] If there's a current session
|
201
292
|
def logged_in?
|
202
|
-
|
293
|
+
!@api.access_token.nil?
|
203
294
|
end
|
204
295
|
|
296
|
+
# Retrieve a list of all registered third-party IDs for the current user
|
297
|
+
#
|
298
|
+
# @return [Response] A response hash containing the key :threepids
|
299
|
+
# @see Protocols::CS#get_3pids
|
300
|
+
def registered_3pids
|
301
|
+
data = api.get_3pids
|
302
|
+
data.threepids.each do |obj|
|
303
|
+
obj.instance_eval do
|
304
|
+
def added_at
|
305
|
+
Time.at(self[:added_at] / 1000)
|
306
|
+
end
|
307
|
+
|
308
|
+
def validated_at
|
309
|
+
return unless validated?
|
310
|
+
|
311
|
+
Time.at(self[:validated_at] / 1000)
|
312
|
+
end
|
313
|
+
|
314
|
+
def validated?
|
315
|
+
key? :validated_at
|
316
|
+
end
|
317
|
+
|
318
|
+
def to_s
|
319
|
+
"#{self[:medium]}:#{self[:address]}"
|
320
|
+
end
|
321
|
+
|
322
|
+
def inspect
|
323
|
+
"#<MatrixSdk::Response 3pid=#{to_s.inspect} added_at=\"#{added_at}\"#{validated? ? " validated_at=\"#{validated_at}\"" : ''}>"
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
data
|
328
|
+
end
|
329
|
+
|
330
|
+
# Creates a new room
|
331
|
+
#
|
332
|
+
# @example Creating a room with an alias
|
333
|
+
# client.create_room('myroom')
|
334
|
+
# #<MatrixSdk::Room ... >
|
335
|
+
#
|
336
|
+
# @param room_alias [String] A default alias to set on the room, should only be the localpart
|
337
|
+
# @return [Room] The resulting room
|
338
|
+
# @see Protocols::CS#create_room
|
205
339
|
def create_room(room_alias = nil, **params)
|
206
340
|
data = api.create_room(params.merge(room_alias: room_alias))
|
207
341
|
ensure_room(data.room_id)
|
208
342
|
end
|
209
343
|
|
344
|
+
# Joins an already created room
|
345
|
+
#
|
346
|
+
# @param room_id_or_alias [String,MXID] A room alias (#room:exmaple.com) or a room ID (!id:example.com)
|
347
|
+
# @param server_name [Array[String]] A list of servers to attempt the join through, required for IDs
|
348
|
+
# @return [Room] The resulting room
|
349
|
+
# @see Protocols::CS#join_room
|
210
350
|
def join_room(room_id_or_alias, server_name: [])
|
211
351
|
server_name = [server_name] unless server_name.is_a? Array
|
212
352
|
data = api.join_room(room_id_or_alias, server_name: server_name)
|
213
353
|
ensure_room(data.fetch(:room_id, room_id_or_alias))
|
214
354
|
end
|
215
355
|
|
356
|
+
# Find a room in the locally cached list of rooms that the current user is part of
|
357
|
+
#
|
358
|
+
# @param room_id_or_alias [String,MXID] A room ID or alias
|
359
|
+
# @param only_canonical [Boolean] Only match alias against the canonical alias
|
360
|
+
# @return [Room] The found room
|
361
|
+
# @return [nil] If no room was found
|
216
362
|
def find_room(room_id_or_alias, only_canonical: false)
|
217
363
|
room_id_or_alias = MXID.new(room_id_or_alias.to_s) unless room_id_or_alias.is_a? MXID
|
218
|
-
raise ArgumentError, 'Must be a room id or alias' unless
|
364
|
+
raise ArgumentError, 'Must be a room id or alias' unless room_id_or_alias.room?
|
219
365
|
|
220
366
|
return @rooms.fetch(room_id_or_alias.to_s, nil) if room_id_or_alias.room_id?
|
221
367
|
|
@@ -224,7 +370,21 @@ module MatrixSdk
|
|
224
370
|
@rooms.values.find { |r| r.aliases.include? room_id_or_alias.to_s }
|
225
371
|
end
|
226
372
|
|
373
|
+
# Get a User instance from a MXID
|
374
|
+
#
|
375
|
+
# @param user_id [String,MXID,:self] The MXID to look up, will also accept :self in order to get the currently logged-in user
|
376
|
+
# @return [User] The User instance for the specified user
|
377
|
+
# @raise [ArgumentError] If the input isn't a valid user ID
|
378
|
+
# @note The method doesn't perform any existence checking, so the returned User object may point to a non-existent user
|
227
379
|
def get_user(user_id)
|
380
|
+
user_id = mxid if user_id == :self
|
381
|
+
|
382
|
+
user_id = MXID.new user_id.to_s unless user_id.is_a? MXID
|
383
|
+
raise ArgumentError, 'Must be a User ID' unless user_id.user?
|
384
|
+
|
385
|
+
# To still use regular string storage in the hash itself
|
386
|
+
user_id = user_id.to_s
|
387
|
+
|
228
388
|
if cache == :all
|
229
389
|
@users[user_id] ||= User.new(self, user_id)
|
230
390
|
else
|
@@ -232,10 +392,23 @@ module MatrixSdk
|
|
232
392
|
end
|
233
393
|
end
|
234
394
|
|
395
|
+
# Remove a room alias
|
396
|
+
#
|
397
|
+
# @param room_alias [String,MXID] The room alias to remove
|
398
|
+
# @see Protocols::CS#remove_room_alias
|
235
399
|
def remove_room_alias(room_alias)
|
400
|
+
room_alias = MXID.new room_alias.to_s unless room_alias.is_a? MXID
|
401
|
+
raise ArgumentError, 'Must be a room alias' unless room_alias.room_alias?
|
402
|
+
|
236
403
|
api.remove_room_alias(room_alias)
|
237
404
|
end
|
238
405
|
|
406
|
+
# Upload a piece of data to the media repo
|
407
|
+
#
|
408
|
+
# @return [URI::MATRIX] A Matrix content (mxc://) URL pointing to the uploaded data
|
409
|
+
# @param content [String] The data to upload
|
410
|
+
# @param content_type [String] The MIME type of the data
|
411
|
+
# @see Protocols::CS#media_upload
|
239
412
|
def upload(content, content_type)
|
240
413
|
data = api.media_upload(content, content_type)
|
241
414
|
return data[:content_uri] if data.key? :content_uri
|
@@ -243,13 +416,19 @@ module MatrixSdk
|
|
243
416
|
raise MatrixUnexpectedResponseError, 'Upload succeeded, but no media URI returned'
|
244
417
|
end
|
245
418
|
|
419
|
+
# Starts a background thread that will listen to new events
|
420
|
+
#
|
421
|
+
# @see sync For What parameters are accepted
|
246
422
|
def start_listener_thread(**params)
|
423
|
+
return if listening?
|
424
|
+
|
247
425
|
@should_listen = true
|
248
426
|
thread = Thread.new { listen_forever(params) }
|
249
427
|
@sync_thread = thread
|
250
428
|
thread.run
|
251
429
|
end
|
252
430
|
|
431
|
+
# Stops the running background thread if one is active
|
253
432
|
def stop_listener_thread
|
254
433
|
return unless @sync_thread
|
255
434
|
|
@@ -258,10 +437,21 @@ module MatrixSdk
|
|
258
437
|
@sync_thread = nil
|
259
438
|
end
|
260
439
|
|
440
|
+
# Check if there's a thread listening for events
|
261
441
|
def listening?
|
262
442
|
@sync_thread&.alive? == true
|
263
443
|
end
|
264
444
|
|
445
|
+
# Run a message sync round, triggering events as necessary
|
446
|
+
#
|
447
|
+
# @param skip_store_batch [Boolean] Should this sync skip storing the returned next_batch token,
|
448
|
+
# doing this would mean the next sync re-runs from the same point. Useful with use of filters.
|
449
|
+
# @param params [Hash] Additional options
|
450
|
+
# @option params [String,Hash] :filter (#sync_filter) A filter to use for this sync
|
451
|
+
# @option params [Numeric] :timeout (30) A timeout value in seconds for the sync request
|
452
|
+
# @option params [Numeric] :allow_sync_retry (0) The number of retries allowed for this sync request
|
453
|
+
# @option params [String] :since An override of the "since" token to provide to the sync request
|
454
|
+
# @see Protocols::CS#sync
|
265
455
|
def sync(skip_store_batch: false, **params)
|
266
456
|
extra_params = {
|
267
457
|
filter: sync_filter,
|
@@ -283,10 +473,27 @@ module MatrixSdk
|
|
283
473
|
@next_batch = data[:next_batch] unless skip_store_batch
|
284
474
|
|
285
475
|
handle_sync_response(data)
|
476
|
+
true
|
286
477
|
end
|
287
478
|
|
288
479
|
alias listen_for_events sync
|
289
480
|
|
481
|
+
# Ensures that a room exists in the cache
|
482
|
+
#
|
483
|
+
# @param room_id [String,MXID] The room ID to ensure
|
484
|
+
# @return [Room] The room object for the requested room
|
485
|
+
def ensure_room(room_id)
|
486
|
+
room_id = MXID.new room_id.to_s unless room_id.is_a? MXID
|
487
|
+
raise ArgumentError, 'Must be a room ID' unless room_id.room_id?
|
488
|
+
|
489
|
+
room_id = room_id.to_s
|
490
|
+
@rooms.fetch(room_id) do
|
491
|
+
room = Room.new(self, room_id)
|
492
|
+
@rooms[room_id] = room unless cache == :none
|
493
|
+
room
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
290
497
|
private
|
291
498
|
|
292
499
|
def listen_forever(timeout: 30, bad_sync_timeout: 5, sync_interval: 30, **params)
|
@@ -320,15 +527,6 @@ module MatrixSdk
|
|
320
527
|
access_token
|
321
528
|
end
|
322
529
|
|
323
|
-
def ensure_room(room_id)
|
324
|
-
room_id = room_id.to_s unless room_id.is_a? String
|
325
|
-
@rooms.fetch(room_id) do
|
326
|
-
room = Room.new(self, room_id)
|
327
|
-
@rooms[room_id] = room unless cache == :none
|
328
|
-
room
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
530
|
def handle_state(room_id, state_event)
|
333
531
|
return unless state_event.key? :type
|
334
532
|
|
@@ -368,10 +566,12 @@ module MatrixSdk
|
|
368
566
|
end
|
369
567
|
|
370
568
|
data[:rooms][:invite].each do |room_id, invite|
|
569
|
+
invite[:room_id] = room_id.to_s
|
371
570
|
fire_invite_event(MatrixEvent.new(self, invite), room_id.to_s)
|
372
571
|
end
|
373
572
|
|
374
573
|
data[:rooms][:leave].each do |room_id, left|
|
574
|
+
left[:room_id] = room_id.to_s
|
375
575
|
fire_leave_event(MatrixEvent.new(self, left), room_id.to_s)
|
376
576
|
end
|
377
577
|
|