matrix_sdk 2.1.3 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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])