matrix_sdk 2.3.0 → 2.4.0

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: fb2cd8492e977a8c63d80d3a250841111f872b45ef48a06ac610dd6c871c5704
4
- data.tar.gz: b5932dc63938f86a4bec522f2d5736871f3a5461ad5d25581c2ba1cd79b20ab2
3
+ metadata.gz: b8fabc9c9f840753916f52925807e2b6282a9fd17fbeedd63f284bd60a1aab86
4
+ data.tar.gz: d0c2330e13f85036bbc0cecf1cde73fc2b960906c497b0cb7fdfe89b49499fd8
5
5
  SHA512:
6
- metadata.gz: 0ed57a7d4b3296a15c244c88ca88777d6ed3f9b67a6c4cdaae017f56c6e15cf94ba0781c6831a70f7adf9c55605073c84c451b0c1b0b8bffe323015330294f19
7
- data.tar.gz: f77aaa05a45917b80aa296b7ff73f37d60ba5fb36f29a3e753cec1a730681a428c33ccdae9f4c26648952d6a7b05f9636e7d7ffbbe8757d23d2c435378d3466b
6
+ metadata.gz: 709c402251e87cd3cb650a7081d121eda551fec86f46dde8c92f2799491810ddb16bd8e44280ced09c0a5daa343385958d8ab19640348cffc2f97eafcb14bcaf
7
+ data.tar.gz: 979fc101ef76e21023b9a6ce41649c0d144a2376429ff3ff6572b0384298d598a30f05ac64e0b2e98013180e7e4b0356a26da214df28ada4c5808e8ae02af331
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 2.4.0 - 2021-07-19
2
+
3
+ - Adds support for matrix: URI's according to MSC2312
4
+ - Adds some basic support for detecting Spaces (MSC1772)
5
+ - Fixes sync against Synapse 1.38.0 missing empty fields
6
+
1
7
  ## 2.3.0 - 2021-03-26
2
8
 
3
9
  - Adds support for Ruby 3.0 (#15)
data/lib/matrix_sdk.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'matrix_sdk/util/extensions'
4
+ require 'matrix_sdk/util/uri'
4
5
  require 'matrix_sdk/version'
5
6
 
6
7
  require 'json'
@@ -22,6 +23,10 @@ module MatrixSdk
22
23
  autoload :MatrixTimeoutError, 'matrix_sdk/errors'
23
24
  autoload :MatrixUnexpectedResponseError, 'matrix_sdk/errors'
24
25
 
26
+ module Rooms
27
+ autoload :Space, 'matrix_sdk/rooms/space'
28
+ end
29
+
25
30
  module Util
26
31
  autoload :Tinycache, 'matrix_sdk/util/tinycache'
27
32
  autoload :TinycacheAdapter, 'matrix_sdk/util/tinycache_adapter'
@@ -73,6 +73,7 @@ module MatrixSdk
73
73
 
74
74
  @cache = client_cache
75
75
  @identity_server = nil
76
+ @mxid = nil
76
77
 
77
78
  @sync_token = nil
78
79
  @sync_thread = nil
@@ -102,9 +103,8 @@ module MatrixSdk
102
103
  #
103
104
  # @return [MXID] The MXID of the current user
104
105
  def mxid
105
- @mxid ||= begin
106
- MXID.new api.whoami?[:user_id] if api&.access_token
107
- end
106
+ @mxid ||= MXID.new api.whoami?[:user_id] if api&.access_token
107
+ @mxid
108
108
  end
109
109
 
110
110
  alias user_id mxid
@@ -161,9 +161,7 @@ module MatrixSdk
161
161
  #
162
162
  # @return [Hash[String,Array[String]]] A mapping of MXIDs to a list of direct rooms with that user
163
163
  def direct_rooms
164
- Hash[api.get_account_data(mxid, 'm.direct').map do |mxid, rooms|
165
- [mxid.to_s, rooms]
166
- end]
164
+ api.get_account_data(mxid, 'm.direct').transform_keys(&:to_s)
167
165
  end
168
166
 
169
167
  # Gets a direct message room for the given user if one exists
@@ -194,6 +192,19 @@ module MatrixSdk
194
192
  @rooms.values
195
193
  end
196
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
+
197
208
  # Refresh the list of currently handled rooms, replacing it with the user's
198
209
  # currently joined rooms.
199
210
  #
@@ -211,6 +222,7 @@ module MatrixSdk
211
222
  true
212
223
  end
213
224
  alias refresh_rooms! reload_rooms!
225
+ alias reload_spaces! reload_rooms!
214
226
 
215
227
  # Register - and log in - on the connected HS as a guest
216
228
  #
@@ -429,13 +441,13 @@ module MatrixSdk
429
441
 
430
442
  # Upload a piece of data to the media repo
431
443
  #
432
- # @return [URI::MATRIX] A Matrix content (mxc://) URL pointing to the uploaded data
444
+ # @return [URI::MXC] A Matrix content (mxc://) URL pointing to the uploaded data
433
445
  # @param content [String] The data to upload
434
446
  # @param content_type [String] The MIME type of the data
435
447
  # @see Protocols::CS#media_upload
436
448
  def upload(content, content_type)
437
449
  data = api.media_upload(content, content_type)
438
- return data[:content_uri] if data.key? :content_uri
450
+ return URI(data[:content_uri]) if data.key? :content_uri
439
451
 
440
452
  raise MatrixUnexpectedResponseError, 'Upload succeeded, but no media URI returned'
441
453
  end
@@ -518,11 +530,9 @@ module MatrixSdk
518
530
 
519
531
  attempts = 0
520
532
  data = loop do
521
- begin
522
- break api.sync **extra_params
523
- rescue MatrixSdk::MatrixTimeoutError => e
524
- raise e if (attempts += 1) >= params.fetch(:allow_sync_retry, 0)
525
- end
533
+ break api.sync(**extra_params)
534
+ rescue MatrixSdk::MatrixTimeoutError => e
535
+ raise e if (attempts += 1) >= params.fetch(:allow_sync_retry, 0)
526
536
  end
527
537
 
528
538
  @next_batch = data[:next_batch] unless skip_store_batch
@@ -592,35 +602,35 @@ module MatrixSdk
592
602
  end
593
603
 
594
604
  def handle_sync_response(data)
595
- data[:presence][:events].each do |presence_update|
605
+ data.dig(:presence, :events)&.each do |presence_update|
596
606
  fire_presence_event(MatrixEvent.new(self, presence_update))
597
607
  end
598
608
 
599
- data[:rooms][:invite].each do |room_id, invite|
609
+ data.dig(:rooms, :invite)&.each do |room_id, invite|
600
610
  invite[:room_id] = room_id.to_s
601
611
  fire_invite_event(MatrixEvent.new(self, invite), room_id.to_s)
602
612
  end
603
613
 
604
- data[:rooms][:leave].each do |room_id, left|
614
+ data.dig(:rooms, :leave)&.each do |room_id, left|
605
615
  left[:room_id] = room_id.to_s
606
616
  fire_leave_event(MatrixEvent.new(self, left), room_id.to_s)
607
617
  end
608
618
 
609
- data[:rooms][:join].each do |room_id, join|
619
+ data.dig(:rooms, :join)&.each do |room_id, join|
610
620
  room = ensure_room(room_id)
611
- room.instance_variable_set '@prev_batch', join[:timeline][:prev_batch]
621
+ room.instance_variable_set '@prev_batch', join.dig(:timeline, :prev_batch)
612
622
  room.instance_variable_set :@members_loaded, true unless sync_filter.fetch(:room, {}).fetch(:state, {}).fetch(:lazy_load_members, false)
613
623
 
614
- join[:state][:events].each do |event|
624
+ join.dig(:state, :events)&.each do |event|
615
625
  event[:room_id] = room_id.to_s
616
626
  handle_state(room_id, event)
617
627
  end
618
628
 
619
- join[:timeline][:events].each do |event|
629
+ join.dig(:timeline, :events)&.each do |event|
620
630
  event[:room_id] = room_id.to_s
621
631
  # Avoid sending two identical state events if it's both in state and timeline
622
632
  if event.key?(:state_key)
623
- state_event = join.dig(:state, :events).find { |ev| ev[:event_id] == event[:event_id] }
633
+ state_event = join.dig(:state, :events)&.find { |ev| ev[:event_id] == event[:event_id] }
624
634
 
625
635
  handle_state(room_id, event) unless event == state_event
626
636
  end
@@ -629,7 +639,7 @@ module MatrixSdk
629
639
  fire_event(MatrixEvent.new(self, event), event[:type])
630
640
  end
631
641
 
632
- join[:ephemeral][:events].each do |event|
642
+ join.dig(:ephemeral, :events)&.each do |event|
633
643
  event[:room_id] = room_id.to_s
634
644
  room.send :put_ephemeral_event, event
635
645
 
@@ -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..-1].split(':')
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?
@@ -100,5 +100,45 @@ module MatrixSdk
100
100
  def room_alias?
101
101
  type == :room_alias
102
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
103
143
  end
104
144
  end
@@ -1435,7 +1435,7 @@ module MatrixSdk::Protocols::CS
1435
1435
  # api.set_avatar_url(api.whoami?[:user_id], mxc)
1436
1436
  #
1437
1437
  # @param [String,MXID] user_id The ID of the user to set the avatar for
1438
- # @param [String,URI::MATRIX] url The new avatar URL, should be a mxc:// URL
1438
+ # @param [String,URI::MXC] url The new avatar URL, should be a mxc:// URL
1439
1439
  # @return [Response] An empty response hash if the change was successful
1440
1440
  # @see https://matrix.org/docs/spec/client_server/latest#put-matrix-client-r0-profile-userid-avatar-url
1441
1441
  # The Matrix Spec, for more information about the event and data
@@ -1545,7 +1545,7 @@ module MatrixSdk::Protocols::CS
1545
1545
  # # => #<URI::HTTPS https://matrix.org/_matrix/media/r0/download/example.com/media_hash>
1546
1546
  def get_download_url(mxcurl, source: nil, **_params)
1547
1547
  mxcurl = URI.parse(mxcurl.to_s) unless mxcurl.is_a? URI
1548
- raise 'Not a mxc:// URL' unless mxcurl.is_a? URI::MATRIX
1548
+ raise 'Not a mxc:// URL' unless mxcurl.is_a? URI::MXC
1549
1549
 
1550
1550
  if source
1551
1551
  source = "https://#{source}" unless source.include? '://'
@@ -28,7 +28,7 @@ module MatrixSdk
28
28
  # An inspect method that skips a handful of instance variables to avoid
29
29
  # flooding the terminal with debug data.
30
30
  # @return [String] a regular inspect string without the data for some variables
31
- ignore_inspect :client, :events, :prev_batch, :logger
31
+ ignore_inspect :client, :events, :prev_batch, :logger, :tinycache_adapter
32
32
 
33
33
  # Requires heavy lookups, so they're cached for an hour
34
34
  cached :joined_members, :aliases, cache_level: :all, expires_in: 60 * 60
@@ -63,6 +63,13 @@ module MatrixSdk
63
63
  # @option data [String,URI] :avatar_url The avatar URL for the room
64
64
  # @option data [String] :prev_batch The previous batch token for backfill
65
65
  def initialize(client, room_id, data = {})
66
+ if client.is_a? Room
67
+ copy = client
68
+ client = copy.client
69
+ room_id = copy.id
70
+ # data = copy.attributes
71
+ end
72
+
66
73
  raise ArgumentError, 'Must be given a Client instance' unless client.is_a? Client
67
74
 
68
75
  @client = client
@@ -71,6 +78,7 @@ module MatrixSdk
71
78
 
72
79
  @events = []
73
80
  @event_history_limit = 10
81
+ @room_type = nil
74
82
 
75
83
  @prev_batch = nil
76
84
 
@@ -89,6 +97,24 @@ module MatrixSdk
89
97
  logger.debug "Created room #{room_id}"
90
98
  end
91
99
 
100
+ #
101
+ # Casting operators
102
+ #
103
+
104
+ def to_space
105
+ return nil unless space?
106
+
107
+ Rooms::Space.new self, nil
108
+ end
109
+
110
+ def to_s
111
+ prefix = canonical_alias if canonical_alias_has_value?
112
+ prefix ||= id
113
+ return "#{prefix} | #{name}" if name_has_value?
114
+
115
+ prefix
116
+ end
117
+
92
118
  #
93
119
  # Event handlers
94
120
  #
@@ -499,6 +525,41 @@ module MatrixSdk
499
525
  true
500
526
  end
501
527
 
528
+ # Gets the room creation information
529
+ #
530
+ # @return [Response] The content of the m.room.create event
531
+ def creation_info
532
+ # Not caching here, easier to cache the important values separately instead
533
+ client.api.get_room_creation_info(id)
534
+ end
535
+
536
+ # Retrieves the type of the room
537
+ #
538
+ # @return ['m.space',String,nil] The type of the room
539
+ def room_type
540
+ # Can't change, so a permanent cache is ok
541
+ return @room_type if @room_type_retrieved || @room_type
542
+
543
+ @room_type_retrieved = true
544
+ @room_type ||= creation_info[:type]
545
+ end
546
+
547
+ # Retrieves the room version
548
+ #
549
+ # @return [String] The version of the room
550
+ def room_version
551
+ @room_version ||= creation_info[:room_version]
552
+ end
553
+
554
+ # Checks if the room is a Matrix Space
555
+ #
556
+ # @return [Boolean,nil] True if the room is a space
557
+ def space?
558
+ room_type == 'm.space'
559
+ rescue MatrixSdk::MatrixForbiddenError, MatrixSdk::MatrixNotFoundError
560
+ nil
561
+ end
562
+
502
563
  # Returns a list of the room tags
503
564
  #
504
565
  # @return [Response] A list of the tags and their data, with add and remove methods implemented
@@ -646,10 +707,10 @@ module MatrixSdk
646
707
 
647
708
  # Sets a new avatar URL for the room
648
709
  #
649
- # @param avatar_url [URI::MATRIX] The mxc:// URL for the new room avatar
710
+ # @param avatar_url [URI::MXC] The mxc:// URL for the new room avatar
650
711
  def avatar_url=(avatar_url)
651
712
  avatar_url = URI(avatar_url) unless avatar_url.is_a? URI
652
- raise ArgumentError, 'Must be a valid MXC URL' unless avatar_url.is_a? URI::MATRIX
713
+ raise ArgumentError, 'Must be a valid MXC URL' unless avatar_url.is_a? URI::MXC
653
714
 
654
715
  client.api.set_room_avatar(id, avatar_url)
655
716
  tinycache_adapter.write(:avatar_url, avatar_url)
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MatrixSdk::Rooms
4
+ class Space < MatrixSdk::Room
5
+ TYPE = 'm.space'
6
+
7
+ def tree(suggested_only: nil, max_rooms: nil)
8
+ begin
9
+ data = client.api.request :get, :client_unstable, "/org.matrix.msc2946/rooms/#{id}/spaces", query: {
10
+ suggested_only: suggested_only,
11
+ max_rooms_per_space: max_rooms
12
+ }.compact
13
+ rescue
14
+ data = client.api.request :get, :client_r0, "/rooms/#{id}/spaces", query: {
15
+ suggested_only: suggested_only,
16
+ max_rooms_per_space: max_rooms
17
+ }.compact
18
+ end
19
+
20
+ rooms = data.rooms.map do |r|
21
+ next if r[:room_id] == id
22
+
23
+ room = client.ensure_room(r[:room_id])
24
+ room.instance_variable_set :@room_type, r[:room_type] if r.key? :room_type
25
+ room = room.to_space if room.space?
26
+
27
+ # Inject available room information
28
+ r.each do |k, v|
29
+ if room.respond_to?("#{k}_cached?".to_sym) && send("#{k}_cached?".to_sym)
30
+ room.send(:tinycache_adapter).write(k, v)
31
+ elsif room.instance_variable_defined? "@#{k}"
32
+ room.instance_variable_set("@#{k}", v)
33
+ end
34
+ end
35
+ room
36
+ end
37
+ rooms.compact!
38
+
39
+ grouping = {}
40
+ data.events.each do |ev|
41
+ next unless ev[:type] == 'm.space.child'
42
+ next unless ev[:content].key? :via
43
+
44
+ d = (grouping[ev[:room_id]] ||= [])
45
+ d << ev[:state_key]
46
+ end
47
+
48
+ build_tree = proc do |entry|
49
+ next if entry.nil?
50
+
51
+ room = self if entry == id
52
+ room ||= rooms.find { |r| r.id == entry }
53
+ puts "Unable to find room for entry #{entry}" unless room
54
+ # next if room.nil?
55
+
56
+ ret = {
57
+ room => []
58
+ }
59
+
60
+ grouping[entry]&.each do |child|
61
+ if grouping.key?(child)
62
+ ret[room] << build_tree.call(child)
63
+ else
64
+ child_r = self if child == id
65
+ child_r ||= rooms.find { |r| r.id == child }
66
+
67
+ ret[room] << child_r
68
+ end
69
+ end
70
+
71
+ ret[room].compact!
72
+
73
+ ret
74
+ end
75
+
76
+ build_tree.call(id)
77
+ end
78
+ end
79
+ end
@@ -59,7 +59,7 @@ module MatrixSdk
59
59
  # Only works for the current user object, as requested by
60
60
  # client.get_user(:self)
61
61
  #
62
- # @param url [String,URI::MATRIX] the new avatar URL
62
+ # @param url [String,URI::MXC] the new avatar URL
63
63
  # @note Requires a mxc:// URL, check example on
64
64
  # {MatrixSdk::Protocols::CS#set_avatar_url} for how this can be done
65
65
  # @see MatrixSdk::Protocols::CS#set_avatar_url
@@ -22,13 +22,11 @@ module MatrixSdk
22
22
 
23
23
  def fire(event, filter = nil)
24
24
  reverse_each do |_k, h|
25
- begin
26
- h[:block].call(event) if !h[:filter] || event.matches?(h[:filter], filter)
27
- rescue StandardError => e
28
- logger.error "#{e.class.name} occurred when firing event (#{event})\n#{e}"
25
+ h[:block].call(event) if !h[:filter] || event.matches?(h[:filter], filter)
26
+ rescue StandardError => e
27
+ logger.error "#{e.class.name} occurred when firing event (#{event})\n#{e}"
29
28
 
30
- raise e if @reraise_exceptions
31
- end
29
+ raise e if @reraise_exceptions
32
30
  end
33
31
  end
34
32
  end
@@ -1,20 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'uri'
4
-
5
- module URI
6
- # A mxc:// Matrix content URL
7
- class MATRIX < Generic
8
- def full_path
9
- select(:host, :port, :path, :query, :fragment)
10
- .reject(&:nil?)
11
- .join
12
- end
13
- end
14
-
15
- @@schemes['MXC'] = MATRIX
16
- end
17
-
18
3
  unless Object.respond_to? :yield_self
19
4
  class Object
20
5
  def yield_self
@@ -68,7 +53,7 @@ module MatrixSdk
68
53
  class_eval %*
69
54
  def inspect
70
55
  reentrant = caller_locations.any? { |l| l.absolute_path == __FILE__ && l.label == 'inspect' }
71
- "\#{to_s[0..-2]} \#{instance_variables
56
+ "\\\#<\#{self.class} \#{instance_variables
72
57
  .reject { |f| %i[#{symbols.map { |s| "@#{s}" }.join ' '}].include? f }
73
58
  .map { |f| "\#{f}=\#{reentrant ? instance_variable_get(f) : instance_variable_get(f).inspect}" }.join " " }}>"
74
59
  end
@@ -20,7 +20,7 @@ module MatrixSdk::Util
20
20
 
21
21
  def self.extended(base)
22
22
  helper_name = base.send(:cache_helper_module_name)
23
- base.remove_const(helper_name) if base.const_defined?(helper_name)
23
+ base.send :remove_const, helper_name if base.const_defined?(helper_name)
24
24
  base.prepend base.const_set(helper_name, Module.new)
25
25
 
26
26
  base.include InstanceMethods
@@ -65,7 +65,10 @@ module MatrixSdk::Util
65
65
  expires: expires_in || 1 * 365 * 24 * 60 * 60 # 1 year
66
66
  }
67
67
 
68
- const_get(cache_helper_module_name).class_eval do
68
+ helper = const_get(cache_helper_module_name)
69
+ return if method_names.any? { |k, _| helper.respond_to? k }
70
+
71
+ helper.class_eval do
69
72
  define_method(method_names[:cache_key]) do |*args|
70
73
  cache_key.call(method_name, args)
71
74
  end
@@ -89,6 +92,10 @@ module MatrixSdk::Util
89
92
  true
90
93
  end
91
94
 
95
+ define_method(method_names[:has_value]) do |*args|
96
+ tinycache_adapter.valid?(__send__(method_names[:cache_key], *args))
97
+ end
98
+
92
99
  define_method(method_name) do |*args|
93
100
  unless_proc = opts[:unless].is_a?(Symbol) ? opts[:unless].to_proc : opts[:unless]
94
101
 
@@ -115,7 +122,8 @@ module MatrixSdk::Util
115
122
  with_cache: "#{method_name}_with_cache#{punctuation}",
116
123
  without_cache: "#{method_name}_without_cache#{punctuation}",
117
124
  clear_cache: "clear_#{method_name}_cache#{punctuation}",
118
- cached: "#{method}_cached?"
125
+ cached: "#{method}_cached?",
126
+ has_value: "#{method}_has_value?"
119
127
  }
120
128
  end
121
129
  end
@@ -16,6 +16,7 @@ module MatrixSdk::Util
16
16
 
17
17
  def write(key, value, expires_in: nil, cache_level: nil)
18
18
  expires_in ||= config.dig(key, :expires)
19
+ expires_in ||= 24 * 60 * 60
19
20
  cache_level ||= client&.cache
20
21
  cache_level ||= :all
21
22
  cache_level = Tinycache::CACHE_LEVELS[cache_level] unless cache_level.is_a? Integer
@@ -30,6 +31,10 @@ module MatrixSdk::Util
30
31
  cache.key?(key)
31
32
  end
32
33
 
34
+ def valid?(key)
35
+ exist?(key) && !cache[key].expired?
36
+ end
37
+
33
38
  def fetch(key, expires_in: nil, cache_level: nil, **_opts)
34
39
  expires_in ||= config.dig(key, :expires)
35
40
  cache_level ||= client&.cache
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+
5
+ module URI
6
+ # A mxc:// Matrix content URL
7
+ class MXC < Generic
8
+ def full_path
9
+ select(:host, :port, :path, :query, :fragment)
10
+ .reject(&:nil?)
11
+ .join
12
+ end
13
+ end
14
+
15
+ @@schemes['MXC'] = MXC
16
+
17
+ unless @@schemes.key? 'MATRIX'
18
+ # A matrix: URI according to MSC2312
19
+ class MATRIX < Generic
20
+ attr_reader :authority, :action, :mxid, :mxid2, :via
21
+
22
+ def initialize(*args)
23
+ super(*args)
24
+
25
+ @action = nil
26
+ @authority = nil
27
+ @mxid = nil
28
+ @mxid2 = nil
29
+ @via = nil
30
+
31
+ raise InvalidComponentError, 'missing opaque part for matrix URL' if !@opaque && !@path
32
+
33
+ if @path
34
+ @authority = @host
35
+ @authority += ":#{@port}" if @port
36
+ else
37
+ @path, @query = @opaque.split('?')
38
+ @query, @fragment = @query.split('#') if @query&.include? '#'
39
+ @path, @fragment = @path.split('#') if @path&.include? '#'
40
+ @path = "/#{path}"
41
+ @opaque = nil
42
+ end
43
+
44
+ components = @path.delete_prefix('/').split('/', -1)
45
+ raise InvalidComponentError, 'component count must be 2 or 4' if components.size != 2 && components.size != 4
46
+
47
+ sigil = case components.shift
48
+ when 'u', 'user'
49
+ '@'
50
+ when 'r', 'room'
51
+ '#'
52
+ when 'roomid'
53
+ '!'
54
+ else
55
+ raise InvalidComponentError, 'invalid component in path'
56
+ end
57
+
58
+ component = components.shift
59
+ raise InvalidComponentError, "component can't be empty" if component.nil? || component.empty?
60
+
61
+ @mxid = MatrixSdk::MXID.new("#{sigil}#{component}")
62
+
63
+ if components.size == 2
64
+ sigil2 = case components.shift
65
+ when 'e', 'event'
66
+ '$'
67
+ else
68
+ raise InvalidComponentError, 'invalid component in path'
69
+ end
70
+ component = components.shift
71
+ raise InvalidComponentError, "component can't be empty" if component.nil? || component.empty?
72
+
73
+ @mxid2 = MatrixSdk::MXID.new("#{sigil2}#{component}")
74
+ end
75
+
76
+ return unless @query
77
+
78
+ @action = @query.match(/action=([^&]+)/)&.captures&.first&.to_sym
79
+ @via = @query.scan(/via=([^&]+)/)&.flatten&.compact
80
+ end
81
+
82
+ def mxid2?
83
+ !@mxid2.nil?
84
+ end
85
+ end
86
+
87
+ @@schemes['MATRIX'] = MATRIX
88
+ end
89
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MatrixSdk
4
- VERSION = '2.3.0'
4
+ VERSION = '2.4.0'
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.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Olofsson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-26 00:00:00.000000000 Z
11
+ date: 2021-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mocha
@@ -105,11 +105,13 @@ files:
105
105
  - lib/matrix_sdk/protocols/ss.rb
106
106
  - lib/matrix_sdk/response.rb
107
107
  - lib/matrix_sdk/room.rb
108
+ - lib/matrix_sdk/rooms/space.rb
108
109
  - lib/matrix_sdk/user.rb
109
110
  - lib/matrix_sdk/util/events.rb
110
111
  - lib/matrix_sdk/util/extensions.rb
111
112
  - lib/matrix_sdk/util/tinycache.rb
112
113
  - lib/matrix_sdk/util/tinycache_adapter.rb
114
+ - lib/matrix_sdk/util/uri.rb
113
115
  - lib/matrix_sdk/version.rb
114
116
  homepage: https://github.com/ananace/ruby-matrix-sdk
115
117
  licenses:
@@ -130,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
132
  - !ruby/object:Gem::Version
131
133
  version: '0'
132
134
  requirements: []
133
- rubygems_version: 3.2.11
135
+ rubygems_version: 3.2.14
134
136
  signing_key:
135
137
  specification_version: 4
136
138
  summary: SDK for applications using the Matrix protocol