matrix_sdk 2.1.2 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -47,7 +47,7 @@ module MatrixSdk::Protocols::MSC
47
47
  query[:user_id] = params.delete(:user_id) if protocol?(:AS) && params.key?(:user_id)
48
48
 
49
49
  req = Net::HTTP::Get.new(homeserver.dup.tap do |u|
50
- u.path = api_to_path(:client_r0) + '/sync/sse'
50
+ u.path = "#{api_to_path :client_r0}/sync/sse"
51
51
  u.query = URI.encode_www_form(query)
52
52
  end)
53
53
  req['accept'] = 'text/event-stream'
@@ -46,7 +46,9 @@ module MatrixSdk
46
46
  attr_reader :api
47
47
 
48
48
  def respond_to_missing?(name, *_args)
49
- key? name
49
+ return true if key? name
50
+
51
+ super
50
52
  end
51
53
 
52
54
  def method_missing(name, *args)
@@ -1,62 +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
- # @!attribute [r] on_event
46
- # @return [EventHandlerArray] The list of event handlers for all events
47
- # @!attribute [r] on_state_event
48
- # @return [EventHandlerArray] The list of event handlers for only state events
49
- # @!attribute [r] on_ephemeral_event
50
- # @return [EventHandlerArray] The list of event handlers for only ephemeral events
51
- events :event, :state_event, :ephemeral_event
52
27
  # @!method inspect
53
28
  # An inspect method that skips a handful of instance variables to avoid
54
29
  # flooding the terminal with debug data.
55
30
  # @return [String] a regular inspect string without the data for some variables
56
- ignore_inspect :client, :members, :events, :prev_batch, :logger,
57
- :on_event, :on_state_event, :on_ephemeral_event
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
58
40
 
59
41
  alias room_id id
42
+ alias members joined_members
60
43
 
61
44
  # Create a new room instance
62
45
  #
@@ -80,40 +63,80 @@ module MatrixSdk
80
63
  # @option data [String,URI] :avatar_url The avatar URL for the room
81
64
  # @option data [String] :prev_batch The previous batch token for backfill
82
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
+
83
73
  raise ArgumentError, 'Must be given a Client instance' unless client.is_a? Client
84
74
 
75
+ @client = client
85
76
  room_id = MXID.new room_id unless room_id.is_a?(MXID)
86
77
  raise ArgumentError, 'room_id must be a valid Room ID' unless room_id.room_id?
87
78
 
88
- event_initialize
89
-
90
- @name = nil
91
- @topic = nil
92
- @canonical_alias = nil
93
- @aliases = []
94
- @join_rule = nil
95
- @guest_access = nil
96
- @world_readable = nil
97
- @members = []
98
79
  @events = []
99
- @members_loaded = false
100
80
  @event_history_limit = 10
101
- @avatar_url = nil
81
+ @room_type = nil
102
82
 
103
83
  @prev_batch = nil
104
84
 
105
85
  data.each do |k, v|
106
- 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
107
93
  end
108
94
 
109
- @client = client
110
95
  @id = room_id.to_s
111
96
 
112
- @name_checked = Time.new(0)
113
-
114
97
  logger.debug "Created room #{room_id}"
115
98
  end
116
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
+
118
+ #
119
+ # Event handlers
120
+ #
121
+
122
+ # @!attribute [r] on_event
123
+ # @return [EventHandlerArray] The list of event handlers for all events
124
+ def on_event
125
+ ensure_room_handlers[:event]
126
+ end
127
+
128
+ # @!attribute [r] on_state_event
129
+ # @return [EventHandlerArray] The list of event handlers for only state events
130
+ def on_state_event
131
+ ensure_room_handlers[:state_event]
132
+ end
133
+
134
+ # @!attribute [r] on_ephemeral_event
135
+ # @return [EventHandlerArray] The list of event handlers for only ephemeral events
136
+ def on_ephemeral_event
137
+ ensure_room_handlers[:ephemeral_event]
138
+ end
139
+
117
140
  #
118
141
  # State readers
119
142
  #
@@ -142,19 +165,22 @@ module MatrixSdk
142
165
  'Empty Room'
143
166
  end
144
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
+
145
175
  # Populates and returns the #members array
146
176
  #
147
177
  # @return [Array(User)] The list of members in the room
148
178
  def joined_members
149
- return members if @members_loaded && !members.empty?
150
-
151
- client.api.get_room_joined_members(id)[:joined].each do |mxid, data|
152
- ensure_member(User.new(client, mxid.to_s,
153
- display_name: data.fetch(:display_name, nil),
154
- 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))
155
183
  end
156
- @members_loaded = true
157
- members
158
184
  end
159
185
 
160
186
  # Get all members (member events) in the room
@@ -174,10 +200,7 @@ module MatrixSdk
174
200
  #
175
201
  # @return [String,nil] The room name - if any
176
202
  def name
177
- return @name if Time.now - @name_checked < 900
178
-
179
- @name_checked = Time.now
180
- @name ||= client.api.get_room_name(id)
203
+ client.api.get_room_name(id)[:name]
181
204
  rescue MatrixNotFoundError
182
205
  # No room name has been specified
183
206
  nil
@@ -187,18 +210,34 @@ module MatrixSdk
187
210
  #
188
211
  # @return [String,nil] The avatar URL - if any
189
212
  def avatar_url
190
- @avatar_url ||= client.api.get_room_avatar(id).url
213
+ client.api.get_room_avatar(id)[:url]
191
214
  rescue MatrixNotFoundError
192
215
  # No avatar has been set
193
216
  nil
194
217
  end
195
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
196
232
  def guest_access
197
- @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
198
234
  end
199
235
 
236
+ # Gets the join rule for the room
237
+ #
238
+ # @return [:public,:knock,:invite,:private] The current join rule
200
239
  def join_rule
201
- @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
202
241
  end
203
242
 
204
243
  # Checks if +guest_access+ is set to +:can_join+
@@ -211,6 +250,34 @@ module MatrixSdk
211
250
  join_rule == :invite
212
251
  end
213
252
 
253
+ # Gets the history visibility of the room
254
+ #
255
+ # @return [:invited,:joined,:shared,:world_readable] The current history visibility for the room
256
+ def history_visibility
257
+ client.api.get_room_state(id, 'm.room.history_visibility')[:history_visibility].to_sym
258
+ end
259
+
260
+ # Checks if the room history is world readable
261
+ #
262
+ # @return [Boolean] If the history is world readable
263
+ def world_readable?
264
+ history_visibility == :world_readable
265
+ end
266
+ alias world_readable world_readable?
267
+
268
+ # Gets the room aliases
269
+ #
270
+ # @return [Array[String]] The assigned room aliases
271
+ def aliases
272
+ client.api.get_room_aliases(id).aliases
273
+ rescue MatrixNotFoundError
274
+ data = client.api.get_room_state_all(id)
275
+ data.select { |chunk| chunk[:type] == 'm.room.aliases' && chunk.key?(:content) && chunk[:content].key?(:aliases) }
276
+ .map { |chunk| chunk[:content][:aliases] }
277
+ .flatten
278
+ .compact
279
+ end
280
+
214
281
  #
215
282
  # Message handling
216
283
  #
@@ -351,7 +418,13 @@ module MatrixSdk
351
418
  # @param reverse [Boolean] whether to fill messages in reverse or not
352
419
  # @param limit [Integer] the maximum number of messages to backfill
353
420
  # @note This will trigger the `on_event` events as messages are added
354
- def backfill_messages(reverse = false, limit = 10)
421
+ def backfill_messages(*args, reverse: false, limit: 10)
422
+ # To be backwards-compatible
423
+ if args.length == 2
424
+ reverse = args.first
425
+ limit = args.last
426
+ end
427
+
355
428
  data = client.api.get_room_messages(id, @prev_batch, direction: :b, limit: limit)
356
429
 
357
430
  events = data[:chunk]
@@ -452,6 +525,41 @@ module MatrixSdk
452
525
  true
453
526
  end
454
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
+
455
563
  # Returns a list of the room tags
456
564
  #
457
565
  # @return [Response] A list of the tags and their data, with add and remove methods implemented
@@ -469,7 +577,7 @@ module MatrixSdk
469
577
  @room
470
578
  end
471
579
  tag_obj.define_singleton_method(:add) do |tag, **data|
472
- @room.add_tag(tag.to_s.to_sym, data)
580
+ @room.add_tag(tag.to_s.to_sym, **data)
473
581
  self[tag.to_s.to_sym] = data
474
582
  self
475
583
  end
@@ -514,22 +622,16 @@ module MatrixSdk
514
622
  #
515
623
  # @param name [String] The new name to set
516
624
  def name=(name)
625
+ tinycache_adapter.write(:name, name)
517
626
  client.api.set_room_name(id, name)
518
- @name = name
627
+ name
519
628
  end
520
629
 
521
630
  # Reloads the name of the room
522
631
  #
523
632
  # @return [Boolean] if the name was changed or not
524
633
  def reload_name!
525
- data = begin
526
- client.api.get_room_name(id)
527
- rescue MatrixNotFoundError
528
- nil
529
- end
530
- changed = data[:name] != @name
531
- @name = data[:name] if changed
532
- changed
634
+ clear_name_cache
533
635
  end
534
636
  alias refresh_name! reload_name!
535
637
 
@@ -537,22 +639,16 @@ module MatrixSdk
537
639
  #
538
640
  # @param topic [String] The new topic to set
539
641
  def topic=(topic)
642
+ tinycache_adapter.write(:topic, topic)
540
643
  client.api.set_room_topic(id, topic)
541
- @topic = topic
644
+ topic
542
645
  end
543
646
 
544
647
  # Reloads the topic of the room
545
648
  #
546
649
  # @return [Boolean] if the topic was changed or not
547
650
  def reload_topic!
548
- data = begin
549
- client.api.get_room_topic(id)
550
- rescue MatrixNotFoundError
551
- nil
552
- end
553
- changed = data[:topic] != @topic
554
- @topic = data[:topic] if changed
555
- changed
651
+ clear_topic_cache
556
652
  end
557
653
  alias refresh_topic! reload_topic!
558
654
 
@@ -561,7 +657,7 @@ module MatrixSdk
561
657
  # @return [Boolean] if the addition was successful or not
562
658
  def add_alias(room_alias)
563
659
  client.api.set_room_alias(id, room_alias)
564
- @aliases << room_alias
660
+ tinycache_adapter.read(:aliases) << room_alias if tinycache_adapter.exist?(:aliases)
565
661
  true
566
662
  end
567
663
 
@@ -571,21 +667,7 @@ module MatrixSdk
571
667
  # @note The list of aliases is not sorted, ordering changes will result in
572
668
  # alias list updates.
573
669
  def reload_aliases!
574
- begin
575
- new_aliases = client.api.get_room_aliases(id).aliases
576
- rescue MatrixNotFoundError
577
- data = client.api.get_room_state_all(id)
578
- new_aliases = data.select { |chunk| chunk[:type] == 'm.room.aliases' && chunk.key?(:content) && chunk[:content].key?(:aliases) }
579
- .map { |chunk| chunk[:content][:aliases] }
580
- .flatten
581
- .compact
582
- end
583
-
584
- return false if new_aliases.nil?
585
-
586
- changed = new_aliases != aliases
587
- @aliases = new_aliases if changed
588
- changed
670
+ clear_aliases_cache
589
671
  end
590
672
  alias refresh_aliases! reload_aliases!
591
673
 
@@ -594,7 +676,7 @@ module MatrixSdk
594
676
  # @param invite_only [Boolean] If it should be invite only or not
595
677
  def invite_only=(invite_only)
596
678
  self.join_rule = invite_only ? :invite : :public
597
- @join_rule == :invite
679
+ invite_only
598
680
  end
599
681
 
600
682
  # Sets the join rule of the room
@@ -602,7 +684,8 @@ module MatrixSdk
602
684
  # @param join_rule [:invite,:public] The join rule of the room
603
685
  def join_rule=(join_rule)
604
686
  client.api.set_room_join_rules(id, join_rule)
605
- @join_rule = join_rule
687
+ tinycache_adapter.write(:join_rule, join_rule)
688
+ join_rule
606
689
  end
607
690
 
608
691
  # Sets if guests are allowed in the room
@@ -610,7 +693,7 @@ module MatrixSdk
610
693
  # @param allow_guests [Boolean] If guests are allowed to join or not
611
694
  def allow_guests=(allow_guests)
612
695
  self.guest_access = (allow_guests ? :can_join : :forbidden)
613
- @guest_access == :can_join
696
+ allow_guests
614
697
  end
615
698
 
616
699
  # Sets the guest access status for the room
@@ -618,18 +701,101 @@ module MatrixSdk
618
701
  # @param guest_access [:can_join,:forbidden] The new guest access status of the room
619
702
  def guest_access=(guest_access)
620
703
  client.api.set_room_guest_access(id, guest_access)
621
- @guest_access = guest_access
704
+ tinycache_adapter.write(:guest_access, guest_access)
705
+ guest_access
622
706
  end
623
707
 
624
708
  # Sets a new avatar URL for the room
625
709
  #
626
- # @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
627
711
  def avatar_url=(avatar_url)
628
712
  avatar_url = URI(avatar_url) unless avatar_url.is_a? URI
629
- 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
630
714
 
631
715
  client.api.set_room_avatar(id, avatar_url)
632
- @avatar_url = avatar_url
716
+ tinycache_adapter.write(:avatar_url, avatar_url)
717
+ avatar_url
718
+ end
719
+
720
+ # Get the power levels of the room
721
+ #
722
+ # @note The returned power levels are cached for a minute
723
+ # @return [Hash] The current power levels as set for the room
724
+ # @see Protocols::CS#get_power_levels
725
+ def power_levels
726
+ client.api.get_power_levels(id)
727
+ end
728
+
729
+ # Gets the power level of a user in the room
730
+ #
731
+ # @param user [User,MXID,String] The user to check the power level for
732
+ # @param use_default [Boolean] Should the user default level be checked if no user-specific one exists
733
+ # @return [Integer,nil] The current power level for the requested user, nil if there's no user specific level
734
+ # and use_default is false
735
+ def user_powerlevel(user, use_default: true)
736
+ user = user.id if user.is_a? User
737
+ user = MXID.new(user.to_s) unless user.is_a? MXID
738
+ raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
739
+
740
+ level = power_levels[:users][user.to_s.to_sym]
741
+ level = power_levels[:users_default] || 0 if level.nil? && use_default
742
+ level
743
+ end
744
+
745
+ # Check if a user is an admin in the room
746
+ #
747
+ # @param user [User,MXID,String] The user to check for admin privileges
748
+ # @param target_level [Integer] The power level that's to be considered as admin privileges
749
+ # @return [Boolean] If the requested user has a power level highe enough to be an admin
750
+ # @see #user_powerlevel
751
+ def admin?(user, target_level: 100)
752
+ level = user_powerlevel(user, use_default: false)
753
+ return false unless level
754
+
755
+ level >= target_level
756
+ end
757
+
758
+ # Make a user an admin in the room
759
+ #
760
+ # @param user [User,MXID,String] The user to give admin privileges
761
+ # @param level [Integer] The power level to set the user to
762
+ # @see #modify_user_power_levels
763
+ def admin!(user, level: 100)
764
+ return true if admin?(user, target_level: level)
765
+
766
+ user = user.id if user.is_a? User
767
+ user = MXID.new(user.to_s) unless user.is_a? MXID
768
+ raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
769
+
770
+ modify_user_power_levels({ user.to_s.to_sym => level })
771
+ end
772
+
773
+ # Check if a user is a moderator in the room
774
+ #
775
+ # @param user [User,MXID,String] The user to check for admin privileges
776
+ # @param target_level [Integer] The power level that's to be considered as admin privileges
777
+ # @return [Boolean] If the requested user has a power level highe enough to be an admin
778
+ # @see #user_powerlevel
779
+ def moderator?(user, target_level: 50)
780
+ level = user_powerlevel(user, use_default: false)
781
+ return false unless level
782
+
783
+ level >= target_level
784
+ end
785
+
786
+ # Make a user a moderator in the room
787
+ #
788
+ # @param user [User,MXID,String] The user to give moderator privileges
789
+ # @param level [Integer] The power level to set the user to
790
+ # @see #modify_user_power_levels
791
+ def moderator!(user, level: 50)
792
+ return true if moderator?(user, target_level: level)
793
+
794
+ user = user.id if user.is_a? User
795
+ user = MXID.new(user.to_s) unless user.is_a? MXID
796
+ raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
797
+
798
+ modify_user_power_levels({ user.to_s.to_sym => level })
633
799
  end
634
800
 
635
801
  # Modifies the power levels of the room
@@ -640,7 +806,8 @@ module MatrixSdk
640
806
  def modify_user_power_levels(users = nil, users_default = nil)
641
807
  return false if users.nil? && users_default.nil?
642
808
 
643
- data = client.api.get_power_levels(id)
809
+ data = power_levels_without_cache
810
+ tinycache_adapter.write(:power_levels, data)
644
811
  data[:users_default] = users_default unless users_default.nil?
645
812
 
646
813
  if users
@@ -661,7 +828,8 @@ module MatrixSdk
661
828
  def modify_required_power_levels(events = nil, params = {})
662
829
  return false if events.nil? && (params.nil? || params.empty?)
663
830
 
664
- data = client.api.get_power_levels(id)
831
+ data = power_levels_without_cache
832
+ tinycache_adapter.write(:power_levels, data)
665
833
  data.merge!(params)
666
834
  data.delete_if { |_k, v| v.nil? }
667
835
 
@@ -678,22 +846,103 @@ module MatrixSdk
678
846
  private
679
847
 
680
848
  def ensure_member(member)
849
+ tinycache_adapter.write(:joined_members, []) unless tinycache_adapter.exist? :joined_members
850
+
851
+ members = tinycache_adapter.read(:joined_members) || []
681
852
  members << member unless members.any? { |m| m.id == member.id }
682
853
  end
683
854
 
855
+ def handle_power_levels(event)
856
+ tinycache_adapter.write(:power_levels, event[:content])
857
+ end
858
+
859
+ def handle_room_name(event)
860
+ tinycache_adapter.write(:name, event[:content][:name])
861
+ end
862
+
863
+ def handle_room_topic(event)
864
+ tinycache_adapter.write(:topic, event[:content][:topic])
865
+ end
866
+
867
+ def handle_room_guest_access(event)
868
+ tinycache_adapter.write(:guest_access, event[:content][:guest_access].to_sym)
869
+ end
870
+
871
+ def handle_room_join_rules(event)
872
+ tinycache_adapter.write(:join_rule, event[:content][:join_rule].to_sym)
873
+ end
874
+
875
+ def handle_room_member(event)
876
+ return unless client.cache == :all
877
+
878
+ if event[:content][:membership] == 'join'
879
+ ensure_member(client.get_user(event[:state_key]).dup.tap do |u|
880
+ u.instance_variable_set :@display_name, event[:content][:displayname]
881
+ end)
882
+ elsif tinycache_adapter.exist? :joined_members
883
+ members = tinycache_adapter.read(:joined_members)
884
+ members.delete_if { |m| m.id == event[:state_key] }
885
+ end
886
+ end
887
+
888
+ def handle_room_canonical_alias(event)
889
+ canonical_alias = tinycache_adapter.write :canonical_alias, event[:content][:alias]
890
+
891
+ data = tinycache_adapter.read(:aliases) || []
892
+ data << canonical_alias
893
+ tinycache_adapter.write(:aliases, data)
894
+ end
895
+
896
+ def handle_room_aliases(event)
897
+ tinycache_adapter.write(:aliases, []) unless tinycache_adapter.exist? :aliases
898
+
899
+ aliases = tinycache_adapter.read(:aliases) || []
900
+ aliases.concat event[:content][:aliases]
901
+
902
+ tinycache_adapter.write(:aliases, aliases)
903
+ end
904
+
905
+ def room_handlers?
906
+ client.instance_variable_get(:@room_handlers).key? id
907
+ end
908
+
909
+ def ensure_room_handlers
910
+ client.instance_variable_get(:@room_handlers)[id] ||= {
911
+ event: MatrixSdk::EventHandlerArray.new,
912
+ state_event: MatrixSdk::EventHandlerArray.new,
913
+ ephemeral_event: MatrixSdk::EventHandlerArray.new
914
+ }
915
+ end
916
+
917
+ INTERNAL_HANDLERS = {
918
+ 'm.room.aliases' => :handle_room_aliases,
919
+ 'm.room.canonical_alias' => :handle_room_canonical_alias,
920
+ 'm.room.guest_access' => :handle_room_guest_access,
921
+ 'm.room.join_rules' => :handle_room_join_rules,
922
+ 'm.room.member' => :handle_room_member,
923
+ 'm.room.name' => :handle_room_name,
924
+ 'm.room.power_levels' => :handle_power_levels,
925
+ 'm.room.topic' => :handle_room_topic
926
+ }.freeze
684
927
  def put_event(event)
928
+ ensure_room_handlers[:event].fire(MatrixEvent.new(self, event), event[:type]) if room_handlers?
929
+
685
930
  @events.push event
686
931
  @events.shift if @events.length > @event_history_limit
687
-
688
- fire_event MatrixEvent.new(self, event)
689
932
  end
690
933
 
691
934
  def put_ephemeral_event(event)
692
- fire_ephemeral_event MatrixEvent.new(self, event)
935
+ return unless room_handlers?
936
+
937
+ ensure_room_handlers[:ephemeral_event].fire(MatrixEvent.new(self, event), event[:type])
693
938
  end
694
939
 
695
940
  def put_state_event(event)
696
- fire_state_event MatrixEvent.new(self, event)
941
+ send(INTERNAL_HANDLERS[event[:type]], event) if INTERNAL_HANDLERS.key? event[:type]
942
+
943
+ return unless room_handlers?
944
+
945
+ ensure_room_handlers[:state_event].fire(MatrixEvent.new(self, event), event[:type])
697
946
  end
698
947
  end
699
948
  end