matrix_sdk 2.1.3 → 2.5.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.
@@ -1,54 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'matrix_sdk'
4
+ require 'matrix_sdk/util/events'
5
+ require 'matrix_sdk/util/tinycache'
4
6
 
5
7
  module MatrixSdk
6
8
  # A class for tracking the information about a room on Matrix
7
9
  class Room
8
10
  extend MatrixSdk::Extensions
11
+ extend MatrixSdk::Util::Tinycache
9
12
  include MatrixSdk::Logging
10
13
 
11
- # @!attribute [rw] canonical_alias
12
- # @return [String, nil] the canonical alias of the room
13
14
  # @!attribute [rw] event_history_limit
14
15
  # @return [Fixnum] the limit of events to keep in the event log
15
- attr_accessor :canonical_alias, :event_history_limit
16
+ attr_accessor :event_history_limit
16
17
  # @!attribute [r] id
17
18
  # @return [String] the internal ID of the room
18
19
  # @!attribute [r] client
19
20
  # @return [Client] the client for the room
20
- # @!attribute [rw] name
21
- # @return [String, nil] the user-provided name of the room
22
- # @see reload_name!
23
- # @!attribute [rw] topic
24
- # @return [String, nil] the user-provided topic of the room
25
- # @see reload_topic!
26
- # @!attribute [r] aliases
27
- # @return [Array(String)] a list of user-set aliases for the room
28
- # @see add_alias
29
- # @see reload_alias!
30
- # @!attribute [rw] join_rule
31
- # @return [:invite, :public] the join rule for the room -
32
- # either +:invite+ or +:public+
33
- # @!attribute [rw] guest_access
34
- # @return [:can_join, :forbidden] the guest access for the room -
35
- # either +:can_join+ or +:forbidden+
36
- # @!attribute [r] members
37
- # @return [Array(User)] the members of the room
38
- # @see reload_members!
39
21
  # @!attribute [r] events
40
22
  # @return [Array(Object)] the last +event_history_limit+ events to arrive in the room
41
23
  # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#get-matrix-client-r0-sync
42
24
  # The timeline events are what will end up in here
43
- attr_reader :id, :client, :topic, :aliases, :members, :events
25
+ attr_reader :id, :client, :events
44
26
 
45
27
  # @!method inspect
46
28
  # An inspect method that skips a handful of instance variables to avoid
47
29
  # flooding the terminal with debug data.
48
30
  # @return [String] a regular inspect string without the data for some variables
49
- ignore_inspect :client, :members, :events, :prev_batch, :logger
31
+ ignore_inspect :client, :events, :prev_batch, :logger, :tinycache_adapter
32
+
33
+ # Requires heavy lookups, so they're cached for an hour
34
+ cached :joined_members, :aliases, cache_level: :all, expires_in: 60 * 60
35
+ # Only cache unfiltered requests for all members
36
+ cached :all_members, unless: proc { |args| args.any? }, cache_level: :all, expires_in: 3600
37
+
38
+ # Much simpler to look up, and lighter data-wise, so the cache is wider
39
+ cached :canonical_alias, :name, :avatar_url, :topic, :guest_access, :join_rule, :power_levels, cache_level: :some, expires_in: 15 * 60
50
40
 
51
41
  alias room_id id
42
+ alias members joined_members
52
43
 
53
44
  # Create a new room instance
54
45
  #
@@ -62,7 +53,7 @@ module MatrixSdk
62
53
  # @option data [String] :topic The current topic of the room
63
54
  # @option data [String,MXID] :canonical_alias The canonical alias of the room
64
55
  # @option data [Array(String,MXID)] :aliases All non-canonical aliases of the room
65
- # @option data [:invite,:public] :join_rule The join rule for the room
56
+ # @option data [:invite,:public,:knock] :join_rule The join rule for the room
66
57
  # @option data [:can_join,:forbidden] :guest_access The guest access setting for the room
67
58
  # @option data [Boolean] :world_readable If the room is readable by the entire world
68
59
  # @option data [Array(User)] :members The list of joined members
@@ -72,38 +63,57 @@ module MatrixSdk
72
63
  # @option data [String,URI] :avatar_url The avatar URL for the room
73
64
  # @option data [String] :prev_batch The previous batch token for backfill
74
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
+
75
73
  raise ArgumentError, 'Must be given a Client instance' unless client.is_a? Client
76
74
 
75
+ @client = client
77
76
  room_id = MXID.new room_id unless room_id.is_a?(MXID)
78
77
  raise ArgumentError, 'room_id must be a valid Room ID' unless room_id.room_id?
79
78
 
80
- @name = nil
81
- @topic = nil
82
- @canonical_alias = nil
83
- @aliases = []
84
- @join_rule = nil
85
- @guest_access = nil
86
- @world_readable = nil
87
- @members = []
88
79
  @events = []
89
- @members_loaded = false
90
80
  @event_history_limit = 10
91
- @avatar_url = nil
81
+ @room_type = nil
92
82
 
93
83
  @prev_batch = nil
94
84
 
95
85
  data.each do |k, v|
96
- instance_variable_set("@#{k}", v) if instance_variable_defined? "@#{k}"
86
+ next if %i[client].include? k
87
+
88
+ if respond_to?("#{k}_cached?".to_sym) && send("#{k}_cached?".to_sym)
89
+ tinycache_adapter.write(k, v)
90
+ elsif instance_variable_defined? "@#{k}"
91
+ instance_variable_set("@#{k}", v)
92
+ end
97
93
  end
98
94
 
99
- @client = client
100
95
  @id = room_id.to_s
101
96
 
102
- @name_checked = Time.new(0)
103
-
104
97
  logger.debug "Created room #{room_id}"
105
98
  end
106
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
107
117
 
108
118
  #
109
119
  # Event handlers
@@ -127,7 +137,6 @@ module MatrixSdk
127
137
  ensure_room_handlers[:ephemeral_event]
128
138
  end
129
139
 
130
-
131
140
  #
132
141
  # State readers
133
142
  #
@@ -156,19 +165,22 @@ module MatrixSdk
156
165
  'Empty Room'
157
166
  end
158
167
 
168
+ # @return [String, nil] the canonical alias of the room
169
+ def canonical_alias
170
+ client.api.get_room_state(id, 'm.room.canonical_alias')[:alias]
171
+ rescue MatrixSdk::MatrixNotFoundError
172
+ nil
173
+ end
174
+
159
175
  # Populates and returns the #members array
160
176
  #
161
177
  # @return [Array(User)] The list of members in the room
162
178
  def joined_members
163
- return members if @members_loaded && !members.empty?
164
-
165
- client.api.get_room_joined_members(id)[:joined].each do |mxid, data|
166
- ensure_member(User.new(client, mxid.to_s,
167
- display_name: data.fetch(:display_name, nil),
168
- avatar_url: data.fetch(:avatar_url, nil)))
179
+ client.api.get_room_joined_members(id)[:joined].map do |mxid, data|
180
+ User.new(client, mxid.to_s,
181
+ display_name: data.fetch(:display_name, nil),
182
+ avatar_url: data.fetch(:avatar_url, nil))
169
183
  end
170
- @members_loaded = true
171
- members
172
184
  end
173
185
 
174
186
  # Get all members (member events) in the room
@@ -188,10 +200,7 @@ module MatrixSdk
188
200
  #
189
201
  # @return [String,nil] The room name - if any
190
202
  def name
191
- return @name if Time.now - @name_checked < 900
192
-
193
- @name_checked = Time.now
194
- @name ||= client.api.get_room_name(id)
203
+ client.api.get_room_name(id)[:name]
195
204
  rescue MatrixNotFoundError
196
205
  # No room name has been specified
197
206
  nil
@@ -201,18 +210,34 @@ module MatrixSdk
201
210
  #
202
211
  # @return [String,nil] The avatar URL - if any
203
212
  def avatar_url
204
- @avatar_url ||= client.api.get_room_avatar(id).url
213
+ client.api.get_room_avatar(id)[:url]
205
214
  rescue MatrixNotFoundError
206
215
  # No avatar has been set
207
216
  nil
208
217
  end
209
218
 
219
+ # Gets the room topic - if any
220
+ #
221
+ # @return [String,nil] The topic of the room
222
+ def topic
223
+ client.api.get_room_topic(id)[:topic]
224
+ rescue MatrixNotFoundError
225
+ # No room name has been specified
226
+ nil
227
+ end
228
+
229
+ # Gets the guest access rights for the room
230
+ #
231
+ # @return [:can_join,:forbidden] The current guest access right
210
232
  def guest_access
211
- @guest_access ||= client.api.get_room_guest_access(id).guest_access.to_sym
233
+ client.api.get_room_guest_access(id)[:guest_access]&.to_sym
212
234
  end
213
235
 
236
+ # Gets the join rule for the room
237
+ #
238
+ # @return [:public,:knock,:invite,:private] The current join rule
214
239
  def join_rule
215
- @join_rule ||= client.api.get_room_join_rules(id).join_rule.to_sym
240
+ client.api.get_room_join_rules(id)[:join_rule]&.to_sym
216
241
  end
217
242
 
218
243
  # Checks if +guest_access+ is set to +:can_join+
@@ -225,6 +250,39 @@ module MatrixSdk
225
250
  join_rule == :invite
226
251
  end
227
252
 
253
+ # Checks if +join_rule+ is set to +:knock+
254
+ def knock_only?
255
+ join_rule == :knock
256
+ end
257
+
258
+ # Gets the history visibility of the room
259
+ #
260
+ # @return [:invited,:joined,:shared,:world_readable] The current history visibility for the room
261
+ def history_visibility
262
+ client.api.get_room_state(id, 'm.room.history_visibility')[:history_visibility]&.to_sym
263
+ end
264
+
265
+ # Checks if the room history is world readable
266
+ #
267
+ # @return [Boolean] If the history is world readable
268
+ def world_readable?
269
+ history_visibility == :world_readable
270
+ end
271
+ alias world_readable world_readable?
272
+
273
+ # Gets the room aliases
274
+ #
275
+ # @return [Array[String]] The assigned room aliases
276
+ def aliases
277
+ client.api.get_room_aliases(id).aliases
278
+ rescue MatrixNotFoundError
279
+ data = client.api.get_room_state_all(id)
280
+ data.select { |chunk| chunk[:type] == 'm.room.aliases' && !chunk.dig(*%i[content aliases]).nil? }
281
+ .map { |chunk| chunk.dig(*%i[content aliases]) }
282
+ .flatten
283
+ .compact
284
+ end
285
+
228
286
  #
229
287
  # Message handling
230
288
  #
@@ -365,7 +423,13 @@ module MatrixSdk
365
423
  # @param reverse [Boolean] whether to fill messages in reverse or not
366
424
  # @param limit [Integer] the maximum number of messages to backfill
367
425
  # @note This will trigger the `on_event` events as messages are added
368
- def backfill_messages(reverse = false, limit = 10)
426
+ def backfill_messages(*args, reverse: false, limit: 10)
427
+ # To be backwards-compatible
428
+ if args.length == 2
429
+ reverse = args.first
430
+ limit = args.last
431
+ end
432
+
369
433
  data = client.api.get_room_messages(id, @prev_batch, direction: :b, limit: limit)
370
434
 
371
435
  events = data[:chunk]
@@ -466,6 +530,41 @@ module MatrixSdk
466
530
  true
467
531
  end
468
532
 
533
+ # Gets the room creation information
534
+ #
535
+ # @return [Response] The content of the m.room.create event
536
+ def creation_info
537
+ # Not caching here, easier to cache the important values separately instead
538
+ client.api.get_room_creation_info(id)
539
+ end
540
+
541
+ # Retrieves the type of the room
542
+ #
543
+ # @return ['m.space',String,nil] The type of the room
544
+ def room_type
545
+ # Can't change, so a permanent cache is ok
546
+ return @room_type if @room_type_retrieved || @room_type
547
+
548
+ @room_type_retrieved = true
549
+ @room_type ||= creation_info[:type]
550
+ end
551
+
552
+ # Retrieves the room version
553
+ #
554
+ # @return [String] The version of the room
555
+ def room_version
556
+ @room_version ||= creation_info[:room_version]
557
+ end
558
+
559
+ # Checks if the room is a Matrix Space
560
+ #
561
+ # @return [Boolean,nil] True if the room is a space
562
+ def space?
563
+ room_type == 'm.space'
564
+ rescue MatrixSdk::MatrixForbiddenError, MatrixSdk::MatrixNotFoundError
565
+ nil
566
+ end
567
+
469
568
  # Returns a list of the room tags
470
569
  #
471
570
  # @return [Response] A list of the tags and their data, with add and remove methods implemented
@@ -483,7 +582,7 @@ module MatrixSdk
483
582
  @room
484
583
  end
485
584
  tag_obj.define_singleton_method(:add) do |tag, **data|
486
- @room.add_tag(tag.to_s.to_sym, data)
585
+ @room.add_tag(tag.to_s.to_sym, **data)
487
586
  self[tag.to_s.to_sym] = data
488
587
  self
489
588
  end
@@ -528,22 +627,16 @@ module MatrixSdk
528
627
  #
529
628
  # @param name [String] The new name to set
530
629
  def name=(name)
630
+ tinycache_adapter.write(:name, name)
531
631
  client.api.set_room_name(id, name)
532
- @name = name
632
+ name
533
633
  end
534
634
 
535
635
  # Reloads the name of the room
536
636
  #
537
637
  # @return [Boolean] if the name was changed or not
538
638
  def reload_name!
539
- data = begin
540
- client.api.get_room_name(id)
541
- rescue MatrixNotFoundError
542
- nil
543
- end
544
- changed = data[:name] != @name
545
- @name = data[:name] if changed
546
- changed
639
+ clear_name_cache
547
640
  end
548
641
  alias refresh_name! reload_name!
549
642
 
@@ -551,22 +644,16 @@ module MatrixSdk
551
644
  #
552
645
  # @param topic [String] The new topic to set
553
646
  def topic=(topic)
647
+ tinycache_adapter.write(:topic, topic)
554
648
  client.api.set_room_topic(id, topic)
555
- @topic = topic
649
+ topic
556
650
  end
557
651
 
558
652
  # Reloads the topic of the room
559
653
  #
560
654
  # @return [Boolean] if the topic was changed or not
561
655
  def reload_topic!
562
- data = begin
563
- client.api.get_room_topic(id)
564
- rescue MatrixNotFoundError
565
- nil
566
- end
567
- changed = data[:topic] != @topic
568
- @topic = data[:topic] if changed
569
- changed
656
+ clear_topic_cache
570
657
  end
571
658
  alias refresh_topic! reload_topic!
572
659
 
@@ -575,7 +662,7 @@ module MatrixSdk
575
662
  # @return [Boolean] if the addition was successful or not
576
663
  def add_alias(room_alias)
577
664
  client.api.set_room_alias(id, room_alias)
578
- @aliases << room_alias
665
+ tinycache_adapter.read(:aliases) << room_alias if tinycache_adapter.exist?(:aliases)
579
666
  true
580
667
  end
581
668
 
@@ -585,21 +672,7 @@ module MatrixSdk
585
672
  # @note The list of aliases is not sorted, ordering changes will result in
586
673
  # alias list updates.
587
674
  def reload_aliases!
588
- begin
589
- new_aliases = client.api.get_room_aliases(id).aliases
590
- rescue MatrixNotFoundError
591
- data = client.api.get_room_state_all(id)
592
- new_aliases = data.select { |chunk| chunk[:type] == 'm.room.aliases' && chunk.key?(:content) && chunk[:content].key?(:aliases) }
593
- .map { |chunk| chunk[:content][:aliases] }
594
- .flatten
595
- .compact
596
- end
597
-
598
- return false if new_aliases.nil?
599
-
600
- changed = new_aliases != aliases
601
- @aliases = new_aliases if changed
602
- changed
675
+ clear_aliases_cache
603
676
  end
604
677
  alias refresh_aliases! reload_aliases!
605
678
 
@@ -608,7 +681,7 @@ module MatrixSdk
608
681
  # @param invite_only [Boolean] If it should be invite only or not
609
682
  def invite_only=(invite_only)
610
683
  self.join_rule = invite_only ? :invite : :public
611
- @join_rule == :invite
684
+ invite_only
612
685
  end
613
686
 
614
687
  # Sets the join rule of the room
@@ -616,7 +689,8 @@ module MatrixSdk
616
689
  # @param join_rule [:invite,:public] The join rule of the room
617
690
  def join_rule=(join_rule)
618
691
  client.api.set_room_join_rules(id, join_rule)
619
- @join_rule = join_rule
692
+ tinycache_adapter.write(:join_rule, join_rule)
693
+ join_rule
620
694
  end
621
695
 
622
696
  # Sets if guests are allowed in the room
@@ -624,7 +698,7 @@ module MatrixSdk
624
698
  # @param allow_guests [Boolean] If guests are allowed to join or not
625
699
  def allow_guests=(allow_guests)
626
700
  self.guest_access = (allow_guests ? :can_join : :forbidden)
627
- @guest_access == :can_join
701
+ allow_guests
628
702
  end
629
703
 
630
704
  # Sets the guest access status for the room
@@ -632,18 +706,101 @@ module MatrixSdk
632
706
  # @param guest_access [:can_join,:forbidden] The new guest access status of the room
633
707
  def guest_access=(guest_access)
634
708
  client.api.set_room_guest_access(id, guest_access)
635
- @guest_access = guest_access
709
+ tinycache_adapter.write(:guest_access, guest_access)
710
+ guest_access
636
711
  end
637
712
 
638
713
  # Sets a new avatar URL for the room
639
714
  #
640
- # @param avatar_url [URI::MATRIX] The mxc:// URL for the new room avatar
715
+ # @param avatar_url [URI::MXC] The mxc:// URL for the new room avatar
641
716
  def avatar_url=(avatar_url)
642
717
  avatar_url = URI(avatar_url) unless avatar_url.is_a? URI
643
- raise ArgumentError, 'Must be a valid MXC URL' unless avatar_url.is_a? URI::MATRIX
718
+ raise ArgumentError, 'Must be a valid MXC URL' unless avatar_url.is_a? URI::MXC
644
719
 
645
720
  client.api.set_room_avatar(id, avatar_url)
646
- @avatar_url = avatar_url
721
+ tinycache_adapter.write(:avatar_url, avatar_url)
722
+ avatar_url
723
+ end
724
+
725
+ # Get the power levels of the room
726
+ #
727
+ # @note The returned power levels are cached for a minute
728
+ # @return [Hash] The current power levels as set for the room
729
+ # @see Protocols::CS#get_power_levels
730
+ def power_levels
731
+ client.api.get_power_levels(id)
732
+ end
733
+
734
+ # Gets the power level of a user in the room
735
+ #
736
+ # @param user [User,MXID,String] The user to check the power level for
737
+ # @param use_default [Boolean] Should the user default level be checked if no user-specific one exists
738
+ # @return [Integer,nil] The current power level for the requested user, nil if there's no user specific level
739
+ # and use_default is false
740
+ def user_powerlevel(user, use_default: true)
741
+ user = user.id if user.is_a? User
742
+ user = MXID.new(user.to_s) unless user.is_a? MXID
743
+ raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
744
+
745
+ level = power_levels.dig(:users, user.to_s.to_sym)
746
+ level = power_levels[:users_default] || 0 if level.nil? && use_default
747
+ level
748
+ end
749
+
750
+ # Check if a user is an admin in the room
751
+ #
752
+ # @param user [User,MXID,String] The user to check for admin privileges
753
+ # @param target_level [Integer] The power level that's to be considered as admin privileges
754
+ # @return [Boolean] If the requested user has a power level highe enough to be an admin
755
+ # @see #user_powerlevel
756
+ def admin?(user, target_level: 100)
757
+ level = user_powerlevel(user, use_default: false)
758
+ return false unless level
759
+
760
+ level >= target_level
761
+ end
762
+
763
+ # Make a user an admin in the room
764
+ #
765
+ # @param user [User,MXID,String] The user to give admin privileges
766
+ # @param level [Integer] The power level to set the user to
767
+ # @see #modify_user_power_levels
768
+ def admin!(user, level: 100)
769
+ return true if admin?(user, target_level: level)
770
+
771
+ user = user.id if user.is_a? User
772
+ user = MXID.new(user.to_s) unless user.is_a? MXID
773
+ raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
774
+
775
+ modify_user_power_levels({ user.to_s.to_sym => level })
776
+ end
777
+
778
+ # Check if a user is a moderator in the room
779
+ #
780
+ # @param user [User,MXID,String] The user to check for admin privileges
781
+ # @param target_level [Integer] The power level that's to be considered as admin privileges
782
+ # @return [Boolean] If the requested user has a power level highe enough to be an admin
783
+ # @see #user_powerlevel
784
+ def moderator?(user, target_level: 50)
785
+ level = user_powerlevel(user, use_default: false)
786
+ return false unless level
787
+
788
+ level >= target_level
789
+ end
790
+
791
+ # Make a user a moderator in the room
792
+ #
793
+ # @param user [User,MXID,String] The user to give moderator privileges
794
+ # @param level [Integer] The power level to set the user to
795
+ # @see #modify_user_power_levels
796
+ def moderator!(user, level: 50)
797
+ return true if moderator?(user, target_level: level)
798
+
799
+ user = user.id if user.is_a? User
800
+ user = MXID.new(user.to_s) unless user.is_a? MXID
801
+ raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
802
+
803
+ modify_user_power_levels({ user.to_s.to_sym => level })
647
804
  end
648
805
 
649
806
  # Modifies the power levels of the room
@@ -654,13 +811,23 @@ module MatrixSdk
654
811
  def modify_user_power_levels(users = nil, users_default = nil)
655
812
  return false if users.nil? && users_default.nil?
656
813
 
657
- data = client.api.get_power_levels(id)
814
+ data = power_levels_without_cache
815
+ tinycache_adapter.write(:power_levels, data)
658
816
  data[:users_default] = users_default unless users_default.nil?
659
817
 
660
818
  if users
661
819
  data[:users] = {} unless data.key? :users
662
- data[:users].merge!(users)
663
- data[:users].delete_if { |_k, v| v.nil? }
820
+ users.each do |user, level|
821
+ user = user.id if user.is_a? User
822
+ user = MXID.new(user.to_s) unless user.is_a? MXID
823
+ raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
824
+
825
+ if level.nil?
826
+ data[:users].delete(user.to_s.to_sym)
827
+ else
828
+ data[:users][user.to_s.to_sym] = level
829
+ end
830
+ end
664
831
  end
665
832
 
666
833
  client.api.set_power_levels(id, data)
@@ -675,7 +842,8 @@ module MatrixSdk
675
842
  def modify_required_power_levels(events = nil, params = {})
676
843
  return false if events.nil? && (params.nil? || params.empty?)
677
844
 
678
- data = client.api.get_power_levels(id)
845
+ data = power_levels_without_cache
846
+ tinycache_adapter.write(:power_levels, data)
679
847
  data.merge!(params)
680
848
  data.delete_if { |_k, v| v.nil? }
681
849
 
@@ -692,9 +860,62 @@ module MatrixSdk
692
860
  private
693
861
 
694
862
  def ensure_member(member)
863
+ tinycache_adapter.write(:joined_members, []) unless tinycache_adapter.exist? :joined_members
864
+
865
+ members = tinycache_adapter.read(:joined_members) || []
695
866
  members << member unless members.any? { |m| m.id == member.id }
696
867
  end
697
868
 
869
+ def handle_power_levels(event)
870
+ tinycache_adapter.write(:power_levels, event[:content])
871
+ end
872
+
873
+ def handle_room_name(event)
874
+ tinycache_adapter.write(:name, event.dig(*%i[content name]))
875
+ end
876
+
877
+ def handle_room_topic(event)
878
+ tinycache_adapter.write(:topic, event.dig(*%i[content topic]))
879
+ end
880
+
881
+ def handle_room_guest_access(event)
882
+ tinycache_adapter.write(:guest_access, event.dig(*%i[content guest_access])&.to_sym)
883
+ end
884
+
885
+ def handle_room_join_rules(event)
886
+ tinycache_adapter.write(:join_rule, event.dig(*%i[content join_rule])&.to_sym)
887
+ end
888
+
889
+ def handle_room_member(event)
890
+ return unless client.cache == :all
891
+
892
+ if event.dig(*%i[content membership]) == 'join'
893
+ ensure_member(client.get_user(event[:state_key]).dup.tap do |u|
894
+ u.instance_variable_set(:@display_name, event.dig(*%i[content displayname]))
895
+ end)
896
+ elsif tinycache_adapter.exist? :joined_members
897
+ members = tinycache_adapter.read(:joined_members)
898
+ members.delete_if { |m| m.id == event[:state_key] }
899
+ end
900
+ end
901
+
902
+ def handle_room_canonical_alias(event)
903
+ canonical_alias = tinycache_adapter.write(:canonical_alias, event.dig(*%i[content alias]))
904
+
905
+ data = tinycache_adapter.read(:aliases) || []
906
+ data << canonical_alias
907
+ tinycache_adapter.write(:aliases, data)
908
+ end
909
+
910
+ def handle_room_aliases(event)
911
+ tinycache_adapter.write(:aliases, []) unless tinycache_adapter.exist? :aliases
912
+
913
+ aliases = tinycache_adapter.read(:aliases) || []
914
+ aliases.concat(event.dig(*%i[content aliases]))
915
+
916
+ tinycache_adapter.write(:aliases, aliases)
917
+ end
918
+
698
919
  def room_handlers?
699
920
  client.instance_variable_get(:@room_handlers).key? id
700
921
  end
@@ -707,6 +928,16 @@ module MatrixSdk
707
928
  }
708
929
  end
709
930
 
931
+ INTERNAL_HANDLERS = {
932
+ 'm.room.aliases' => :handle_room_aliases,
933
+ 'm.room.canonical_alias' => :handle_room_canonical_alias,
934
+ 'm.room.guest_access' => :handle_room_guest_access,
935
+ 'm.room.join_rules' => :handle_room_join_rules,
936
+ 'm.room.member' => :handle_room_member,
937
+ 'm.room.name' => :handle_room_name,
938
+ 'm.room.power_levels' => :handle_power_levels,
939
+ 'm.room.topic' => :handle_room_topic
940
+ }.freeze
710
941
  def put_event(event)
711
942
  ensure_room_handlers[:event].fire(MatrixEvent.new(self, event), event[:type]) if room_handlers?
712
943
 
@@ -721,6 +952,8 @@ module MatrixSdk
721
952
  end
722
953
 
723
954
  def put_state_event(event)
955
+ send(INTERNAL_HANDLERS[event[:type]], event) if INTERNAL_HANDLERS.key? event[:type]
956
+
724
957
  return unless room_handlers?
725
958
 
726
959
  ensure_room_handlers[:state_event].fire(MatrixEvent.new(self, event), event[:type])