matrix_sdk 2.3.0 → 2.4.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 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