matrix_sdk 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e0e5819346e56fd4eac1564434e88399500adefe0def16bc706a25ec7a254b2
4
- data.tar.gz: 2d74cd2d5203f5431396b03717c4302f9a0c7816c47eaa969e2395ab2eb46586
3
+ metadata.gz: e1de46ea35a8763e17d834c9395dc95a12c3084557085a0eb6b8e5f1fa25979a
4
+ data.tar.gz: 13a55698bf72695e8e690d4d5f6618d7efe595f06c32c65580b10e9bf550724e
5
5
  SHA512:
6
- metadata.gz: 7eb8ef8277b0bda1191915e5be4dcf93856cd876f611b77974b8dc88e5e230ba5c3300995157f9717a4b00d1a7cba7f7a618844cc436ad0b6a3ea5865367049d
7
- data.tar.gz: bd888c36cf3a082360dbecc408c0a67e16ddb337a721105be7abf3a9662d81bfa564a1093a64d1f934d484af6a22a36e5b91bafde70f02a882e6d092e81d5459
6
+ metadata.gz: 919a27ee7fd758c382eafe3f8aad89c13da2a6cc6542ccd8bfe52d09186d93453b12406dfe6b03b6aa63d1898dbacfb6dbced4f4e9606722ad04df4f237cf600
7
+ data.tar.gz: a8f5c0bc4fb07a089e0d1daebeb8996c6d36157550e73e3869a8bb55f25cc2c405a064654fc49c8bdb323f9d8c168b3c785e52b9f88fbc168ee29c152f7472a5
@@ -1,3 +1,8 @@
1
+ ## 2.0.1 - 2020-03-13
2
+
3
+ - Add code for handling non-final MSC's in protocols
4
+ - Currently implementing clients parts of MSC2018 for Sync over Server Sent Events
5
+
1
6
  ## 2.0.0 - 2020-02-14
2
7
 
3
8
  **NB**, this release includes backwards-incompatible changes;
@@ -27,6 +27,9 @@ module MatrixSdk
27
27
  autoload :CS, 'matrix_sdk/protocols/cs'
28
28
  autoload :IS, 'matrix_sdk/protocols/is'
29
29
  autoload :SS, 'matrix_sdk/protocols/ss'
30
+
31
+ # Non-final protocol extensions
32
+ autoload :MSC, 'matrix_sdk/protocols/msc'
30
33
  end
31
34
 
32
35
  def self.debug!
@@ -11,10 +11,6 @@ module MatrixSdk
11
11
  class Api
12
12
  extend MatrixSdk::Extensions
13
13
  include MatrixSdk::Logging
14
- include MatrixSdk::Protocols::AS
15
- include MatrixSdk::Protocols::CS
16
- include MatrixSdk::Protocols::IS
17
- include MatrixSdk::Protocols::SS
18
14
 
19
15
  USER_AGENT = "Ruby Matrix SDK v#{MatrixSdk::VERSION}"
20
16
  DEFAULT_HEADERS = {
@@ -23,7 +19,7 @@ module MatrixSdk
23
19
  }.freeze
24
20
 
25
21
  attr_accessor :access_token, :connection_address, :connection_port, :device_id, :autoretry, :global_headers
26
- attr_reader :homeserver, :validate_certificate, :open_timeout, :read_timeout, :protocols, :well_known, :proxy_uri
22
+ attr_reader :homeserver, :validate_certificate, :open_timeout, :read_timeout, :well_known, :proxy_uri
27
23
 
28
24
  ignore_inspect :access_token, :logger
29
25
 
@@ -51,10 +47,6 @@ module MatrixSdk
51
47
  @homeserver.path.gsub!(/\/?_matrix\/?/, '') if @homeserver.path =~ /_matrix\/?$/
52
48
  raise ArgumentError, 'Please use the base URL for your HS (without /_matrix/)' if @homeserver.path.include? '/_matrix/'
53
49
 
54
- @protocols = params.fetch(:protocols, %i[CS])
55
- @protocols = [@protocols] unless @protocols.is_a? Array
56
- @protocols << :CS if @protocols.include?(:AS) && !@protocols.include?(:CS)
57
-
58
50
  @proxy_uri = params.fetch(:proxy_uri, nil)
59
51
  @connection_address = params.fetch(:address, nil)
60
52
  @connection_port = params.fetch(:port, nil)
@@ -71,6 +63,10 @@ module MatrixSdk
71
63
  @global_headers.merge!(params.fetch(:global_headers)) if params.key? :global_headers
72
64
  @http = nil
73
65
 
66
+ ([params.fetch(:protocols, [:CS])].flatten - protocols).each do |proto|
67
+ self.class.include MatrixSdk::Protocols.const_get(proto)
68
+ end
69
+
74
70
  login(user: @homeserver.user, password: @homeserver.password) if @homeserver.user && @homeserver.password && !@access_token && !params[:skip_login] && protocol?(:CS)
75
71
  @homeserver.userinfo = '' unless params[:skip_login]
76
72
  end
@@ -155,6 +151,20 @@ module MatrixSdk
155
151
  ))
156
152
  end
157
153
 
154
+ # Get a list of enabled protocols on the API client
155
+ #
156
+ # @example
157
+ # MatrixSdk::Api.new_for_domain('matrix.org').protocols
158
+ # # => [:IS, :CS]
159
+ #
160
+ # @return [Symbol[]] An array of enabled APIs
161
+ def protocols
162
+ self
163
+ .class.included_modules
164
+ .select { |m| m.name.start_with? 'MatrixSdk::Protocols::' }
165
+ .map { |m| m.name.split('::').last.to_sym }
166
+ end
167
+
158
168
  # Check if a protocol is enabled on the API connection
159
169
  #
160
170
  # @example Checking for identity server API support
@@ -233,6 +243,7 @@ module MatrixSdk
233
243
  # @option options [Hash,String] :body The body to attach to the request, will be JSON-encoded if sent as a hash
234
244
  # @option options [IO] :body_stream A body stream to attach to the request
235
245
  # @option options [Hash] :headers Additional headers to set on the request
246
+ # @option options [Boolean] :skip_auth (false) Skip authentication
236
247
  def request(method, api, path, **options)
237
248
  url = homeserver.dup.tap do |u|
238
249
  u.path = api_to_path(api) + path
@@ -250,7 +261,7 @@ module MatrixSdk
250
261
  request.content_length = (request.body || request.body_stream).size
251
262
  end
252
263
 
253
- request['authorization'] = "Bearer #{access_token}" if access_token
264
+ request['authorization'] = "Bearer #{access_token}" if access_token && !options.fetch(:skip_auth, false)
254
265
  if options.key? :headers
255
266
  options[:headers].each do |h, v|
256
267
  request[h.to_s.downcase] = v
@@ -289,7 +300,7 @@ module MatrixSdk
289
300
 
290
301
  private
291
302
 
292
- def print_http(http)
303
+ def print_http(http, body: true)
293
304
  return unless logger.debug?
294
305
 
295
306
  if http.is_a? Net::HTTPRequest
@@ -303,10 +314,12 @@ module MatrixSdk
303
314
  logger.debug "#{dir} #{h}"
304
315
  end
305
316
  logger.debug dir
306
- clean_body = JSON.parse(http.body) rescue nil if http.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
309
- logger.debug "#{dir} #{clean_body.length < 200 ? clean_body : clean_body.slice(0..200) + "... [truncated, #{clean_body.length} Bytes]"}" if clean_body
317
+ if body
318
+ clean_body = JSON.parse(http.body) rescue nil if http.body
319
+ clean_body.keys.each { |k| clean_body[k] = '[ REDACTED ]' if %w[password access_token].include?(k) }.to_json if clean_body.is_a? Hash
320
+ clean_body = clean_body.to_s if clean_body
321
+ logger.debug "#{dir} #{clean_body.length < 200 ? clean_body : clean_body.slice(0..200) + "... [truncated, #{clean_body.length} Bytes]"}" if clean_body
322
+ end
310
323
  rescue StandardError => e
311
324
  logger.warn "#{e.class} occured while printing request debug; #{e.message}\n#{e.backtrace.join "\n"}"
312
325
  end
@@ -423,7 +423,16 @@ module MatrixSdk
423
423
  return if listening?
424
424
 
425
425
  @should_listen = true
426
- thread = Thread.new { listen_forever(params) }
426
+ if api.protocol?(:MSC) && api.msc2108?
427
+ params[:since] = @next_batch if @next_batch
428
+ thread = api.msc2108_sync_sse(params) do |data, event:, id:|
429
+ logger.debug "Handling SSE event '#{event}' from '#{id}'"
430
+ @next_batch = id if id
431
+ handle_sync_response(data) if event.to_sym == :sync
432
+ end
433
+ else
434
+ thread = Thread.new { listen_forever(params) }
435
+ end
427
436
  @sync_thread = thread
428
437
  thread.run
429
438
  end
@@ -10,6 +10,7 @@ module MatrixSdk
10
10
  raise ArgumentError, 'Identifier is too long' if identifier.size > 255
11
11
  raise ArgumentError, 'Identifier lacks required data' unless identifier =~ %r{^([@!$+#][^:]+:[^:]+(?::\d+)?)|(\$[A-Za-z0-9+/]+)$}
12
12
 
13
+ # TODO: Community-as-a-Room / Profile-as-a-Room, in case they're going for room aliases
13
14
  @sigil = identifier[0]
14
15
  @localpart, @domain, @port = identifier[1..-1].split(':')
15
16
  @port = @port.to_i if @port
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Preliminary support for unmerged MSCs (Matrix Spec Changes)
4
+ module MatrixSdk::Protocols::MSC
5
+ def self.included(_)
6
+ @msc = {}
7
+ end
8
+
9
+ def refresh_mscs
10
+ @msc = {}
11
+ end
12
+
13
+ # Check if there's support for MSC2108 - Sync over Server Sent Events
14
+ def msc2108?
15
+ @msc[2108] ||= \
16
+ begin
17
+ request(:get, :client_r0, '/sync/sse', skip_auth: true, headers: { accept: 'text/event-stream' })
18
+ rescue MatrixSdk::MatrixNotAuthorizedError # Returns 401 if implemented
19
+ true
20
+ rescue MatrixSdk::MatrixRequestError
21
+ false
22
+ end
23
+ end
24
+
25
+ # Sync over Server Sent Events - MSC2108
26
+ #
27
+ # @note With the default Ruby Net::HTTP server, body fragments are cached up to 16kB,
28
+ # which will result in large batches and delays if your filters trim a lot of data.
29
+ #
30
+ # @example Syncing over SSE
31
+ # @since = 'some token'
32
+ # api.msc2108_sync_sse(since: @since) do |data, event:, id:|
33
+ # if event == 'sync'
34
+ # handle(data) # data is the same as a normal sync response
35
+ # @since = id
36
+ # end
37
+ # end
38
+ #
39
+ # @see Protocols::CS#sync
40
+ # @see https://github.com/matrix-org/matrix-doc/pull/2108/
41
+ def msc2108_sync_sse(since: nil, **params, &on_data)
42
+ raise ArgumentError, 'Must be given a block accepting two args - data and { event:, id: }' \
43
+ unless on_data.is_a?(Proc) && on_data.arity == 2
44
+ raise MatrixNotAuthorizedError unless access_token
45
+
46
+ query = params.select do |k, _v|
47
+ %i[filter full_state set_presence].include? k
48
+ end
49
+ query[:user_id] = params.delete(:user_id) if protocol?(:AS) && params.key?(:user_id)
50
+
51
+ req = Net::HTTP::Get.new(homeserver.dup.tap do |u|
52
+ u.path = api_to_path(:client_r0) + '/sync/sse'
53
+ u.query = URI.encode_www_form(query)
54
+ end)
55
+ req['accept'] = 'text/event-stream'
56
+ req['authorization'] = "Bearer #{access_token}"
57
+ req['last-event-id'] = since if since
58
+
59
+ # rubocop:disable Metrics/BlockLength
60
+ thread = Thread.new do
61
+ print_http(req)
62
+ http.request req do |response|
63
+ print_http(response, body: false)
64
+ raise MatrixRequestError.new_by_code(JSON.parse(response.body, symbolize_names: true), response.code) unless response.is_a? Net::HTTPSuccess
65
+
66
+ buffer = ''
67
+ response.read_body do |chunk|
68
+ buffer += chunk
69
+ logger.debug "< MSC2108: Received #{chunk.length}B of data."
70
+
71
+ while (index = buffer.index(/\r\n\r\n|\n\n/))
72
+ stream = buffer.slice!(0..index)
73
+
74
+ data = ''
75
+ event = nil
76
+ id = nil
77
+
78
+ stream.split(/\r?\n/).each do |part|
79
+ /^data:(.+)$/.match(part) do |m_data|
80
+ data += "\n" unless data.empty?
81
+ data += m_data[1].strip
82
+ end
83
+ /^event:(.+)$/.match(part) do |m_event|
84
+ event = m_event[1].strip
85
+ end
86
+ /^id:(.+)$/.match(part) do |m_id|
87
+ id = m_id[1].strip
88
+ end
89
+ end
90
+
91
+ data = JSON.parse(data, symbolize_names: true)
92
+
93
+ yield((MatrixSdk::Response.new self, data), event: event, id: id)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ # rubocop:enable Metrics/BlockLength
99
+
100
+ thread.abort_on_exception = true
101
+ thread.run
102
+
103
+ thread
104
+ end
105
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MatrixSdk
4
- VERSION = '2.0.0'
4
+ VERSION = '2.0.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matrix_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Olofsson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-14 00:00:00.000000000 Z
11
+ date: 2020-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mocha
@@ -103,6 +103,7 @@ files:
103
103
  - lib/matrix_sdk/protocols/as.rb
104
104
  - lib/matrix_sdk/protocols/cs.rb
105
105
  - lib/matrix_sdk/protocols/is.rb
106
+ - lib/matrix_sdk/protocols/msc.rb
106
107
  - lib/matrix_sdk/protocols/ss.rb
107
108
  - lib/matrix_sdk/response.rb
108
109
  - lib/matrix_sdk/room.rb