matrix_sdk 2.4.0 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -60,7 +60,9 @@ module MatrixSdk::Protocols::MSC
60
60
  # rubocop:disable Metrics/BlockLength
61
61
  thread = Thread.new(cancellation_token) do |ctx|
62
62
  print_http(req)
63
+ @http_lock&.lock
63
64
  http.request req do |response|
65
+ @http_lock&.unlock
64
66
  break unless ctx[:run]
65
67
 
66
68
  print_http(response, body: false)
@@ -134,8 +136,11 @@ module MatrixSdk::Protocols::MSC
134
136
  break
135
137
  end
136
138
  end
139
+
137
140
  break unless ctx[:run]
138
141
  end
142
+ ensure
143
+ @http_lock.unlock if @http_lock&.owned?
139
144
  end
140
145
  # rubocop:enable Metrics/BlockLength
141
146
 
@@ -31,6 +31,8 @@ module MatrixSdk
31
31
  return data
32
32
  end
33
33
 
34
+ return data if data.instance_variables.include? :@api
35
+
34
36
  raise ArgumentError, 'Input data was not a hash' unless data.is_a? Hash
35
37
 
36
38
  data.extend(Extensions)
@@ -31,9 +31,11 @@ module MatrixSdk
31
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
- 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
34
+ cached :joined_members, cache_level: :all, expires_in: 60 * 60
35
+
36
+ # Only cache unfiltered requests for aliases and members
37
+ cached :aliases, unless: proc { |args| args.any? }, cache_level: :all, expires_in: 60 * 60
38
+ cached :all_members, unless: proc { |args| args.any? }, cache_level: :all, expires_in: 60 * 60
37
39
 
38
40
  # Much simpler to look up, and lighter data-wise, so the cache is wider
39
41
  cached :canonical_alias, :name, :avatar_url, :topic, :guest_access, :join_rule, :power_levels, cache_level: :some, expires_in: 15 * 60
@@ -53,7 +55,7 @@ module MatrixSdk
53
55
  # @option data [String] :topic The current topic of the room
54
56
  # @option data [String,MXID] :canonical_alias The canonical alias of the room
55
57
  # @option data [Array(String,MXID)] :aliases All non-canonical aliases of the room
56
- # @option data [:invite,:public] :join_rule The join rule for the room
58
+ # @option data [:invite,:public,:knock] :join_rule The join rule for the room
57
59
  # @option data [:can_join,:forbidden] :guest_access The guest access setting for the room
58
60
  # @option data [Boolean] :world_readable If the room is readable by the entire world
59
61
  # @option data [Array(User)] :members The list of joined members
@@ -125,6 +127,12 @@ module MatrixSdk
125
127
  ensure_room_handlers[:event]
126
128
  end
127
129
 
130
+ # @!attribute [r] on_account_data
131
+ # @return [EventHandlerArray] The list of event handlers for account data changes
132
+ def on_account_data
133
+ ensure_room_handlers[:account_data]
134
+ end
135
+
128
136
  # @!attribute [r] on_state_event
129
137
  # @return [EventHandlerArray] The list of event handlers for only state events
130
138
  def on_state_event
@@ -206,6 +214,32 @@ module MatrixSdk
206
214
  nil
207
215
  end
208
216
 
217
+ # Checks if the room is a direct message / 1:1 room
218
+ #
219
+ # @param members_only [Boolean] Should directness only care about member count?
220
+ # @return [Boolean]
221
+ def dm?(members_only: false)
222
+ return true if !members_only && client.direct_rooms.any? { |_uid, rooms| rooms.include? id.to_s }
223
+
224
+ joined_members.count <= 2
225
+ end
226
+
227
+ # Mark a room as a direct (1:1) message Room
228
+ def dm=(direct)
229
+ rooms = client.direct_rooms
230
+ dirty = false
231
+ list_for_room = (rooms[id.to_s] ||= [])
232
+ if direct && !list_for_room.include?(id.to_s)
233
+ list_for_room << id.to_s
234
+ dirty = true
235
+ elsif !direct && list_for_room.include?(id.to_s)
236
+ list_for_room.delete id.to_s
237
+ rooms.delete id.to_s if list_for_room.empty?
238
+ dirty = true
239
+ end
240
+ client.account_data['m.direct'] = rooms if dirty
241
+ end
242
+
209
243
  # Gets the avatar url of the room - if any
210
244
  #
211
245
  # @return [String,nil] The avatar URL - if any
@@ -230,14 +264,14 @@ module MatrixSdk
230
264
  #
231
265
  # @return [:can_join,:forbidden] The current guest access right
232
266
  def guest_access
233
- client.api.get_room_guest_access(id)[:guest_access].to_sym
267
+ client.api.get_room_guest_access(id)[:guest_access]&.to_sym
234
268
  end
235
269
 
236
270
  # Gets the join rule for the room
237
271
  #
238
272
  # @return [:public,:knock,:invite,:private] The current join rule
239
273
  def join_rule
240
- client.api.get_room_join_rules(id)[:join_rule].to_sym
274
+ client.api.get_room_join_rules(id)[:join_rule]&.to_sym
241
275
  end
242
276
 
243
277
  # Checks if +guest_access+ is set to +:can_join+
@@ -250,11 +284,16 @@ module MatrixSdk
250
284
  join_rule == :invite
251
285
  end
252
286
 
287
+ # Checks if +join_rule+ is set to +:knock+
288
+ def knock_only?
289
+ join_rule == :knock
290
+ end
291
+
253
292
  # Gets the history visibility of the room
254
293
  #
255
294
  # @return [:invited,:joined,:shared,:world_readable] The current history visibility for the room
256
295
  def history_visibility
257
- client.api.get_room_state(id, 'm.room.history_visibility')[:history_visibility].to_sym
296
+ client.api.get_room_state(id, 'm.room.history_visibility')[:history_visibility]&.to_sym
258
297
  end
259
298
 
260
299
  # Checks if the room history is world readable
@@ -267,15 +306,14 @@ module MatrixSdk
267
306
 
268
307
  # Gets the room aliases
269
308
  #
309
+ # @param canonical_only [Boolean] Should the list of aliases only contain the canonical ones
270
310
  # @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
311
+ def aliases(canonical_only: true)
312
+ canonical = client.api.get_room_state(id, 'm.room.canonical_alias') rescue {}
313
+ aliases = ([canonical[:alias]].compact + (canonical[:alt_aliases] || [])).uniq.sort
314
+ return aliases if canonical_only
315
+
316
+ (aliases + client.api.get_room_aliases(id).aliases).uniq.sort
279
317
  end
280
318
 
281
319
  #
@@ -394,6 +432,31 @@ module MatrixSdk
394
432
  client.api.send_content(id, url, name, 'm.audio', extra_information: audio_info)
395
433
  end
396
434
 
435
+ # Sends a customized message to the Room
436
+ #
437
+ # @param body [String] The clear-text body of the message
438
+ # @param content [Hash] The custom content of the message
439
+ # @param msgtype [String] The type of the message, should be one of the known types (m.text, m.notice, m.emote, etc)
440
+ def send_custom_message(body, content = {}, msgtype: nil)
441
+ content.merge!(
442
+ body: body,
443
+ msgtype: msgtype || 'm.text'
444
+ )
445
+
446
+ client.api.send_message_event(id, 'm.room.message', content)
447
+ end
448
+
449
+ # Sends a custom timeline event to the Room
450
+ #
451
+ # @param type [String,Symbol] The type of the Event.
452
+ # For custom events, this should be written in reverse DNS format (e.g. com.example.event)
453
+ # @param content [Hash] The contents of the message, this will be the
454
+ # :content key of the resulting event object
455
+ # @see Protocols::CS#send_message_event
456
+ def send_event(type, content = {})
457
+ client.api.send_message_event(id, type, content)
458
+ end
459
+
397
460
  # Redacts a message from the room
398
461
  #
399
462
  # @param event_id [String] the ID of the event to redact
@@ -490,12 +553,18 @@ module MatrixSdk
490
553
  true
491
554
  end
492
555
 
556
+ def account_data
557
+ return MatrixSdk::Util::AccountDataCache.new client, room: self if client.cache == :none
558
+
559
+ @account_data ||= MatrixSdk::Util::AccountDataCache.new client, room: self
560
+ end
561
+
493
562
  # Retrieves a custom entry from the room-specific account data
494
563
  #
495
564
  # @param type [String] the data type to retrieve
496
565
  # @return [Hash] the data that was stored under the given type
497
566
  def get_account_data(type)
498
- client.api.get_room_account_data(client.mxid, id, type)
567
+ account_data[type]
499
568
  end
500
569
 
501
570
  # Stores a custom entry into the room-specific account data
@@ -503,7 +572,7 @@ module MatrixSdk
503
572
  # @param type [String] the data type to store
504
573
  # @param account_data [Hash] the data to store
505
574
  def set_account_data(type, account_data)
506
- client.api.set_room_account_data(client.mxid, id, type, account_data)
575
+ self.account_data[type] = account_data
507
576
  true
508
577
  end
509
578
 
@@ -735,13 +804,27 @@ module MatrixSdk
735
804
  def user_powerlevel(user, use_default: true)
736
805
  user = user.id if user.is_a? User
737
806
  user = MXID.new(user.to_s) unless user.is_a? MXID
738
- raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
807
+ raise ArgumentError, 'Must provide a valid User or MXID' unless user.user?
739
808
 
740
- level = power_levels[:users][user.to_s.to_sym]
741
- level = power_levels[:users_default] || 0 if level.nil? && use_default
809
+ level = power_levels.dig(:users, user.to_s.to_sym)
810
+ level ||= power_levels[:users_default] || 0 if use_default
742
811
  level
743
812
  end
744
813
 
814
+ # Checks if a user can send a given event type in the room
815
+ #
816
+ # @param user [User,MXID,String] The user to check
817
+ # @param event [String,Symbol] The event type to check
818
+ # @param state [Boolean] If the given event is a state event or a message event
819
+ # @return [Boolean] If the given user is allowed to send an event of the given type
820
+ def user_can_send?(user, event, state: false)
821
+ user_pl = user_powerlevel(user)
822
+ event_pl = power_levels.dig(:events, event.to_s.to_sym)
823
+ event_pl ||= state ? (power_levels[:state_default] || 50) : (power_levels[:events_default] || 0)
824
+
825
+ user_pl >= event_pl
826
+ end
827
+
745
828
  # Check if a user is an admin in the room
746
829
  #
747
830
  # @param user [User,MXID,String] The user to check for admin privileges
@@ -812,8 +895,17 @@ module MatrixSdk
812
895
 
813
896
  if users
814
897
  data[:users] = {} unless data.key? :users
815
- data[:users].merge!(users)
816
- data[:users].delete_if { |_k, v| v.nil? }
898
+ users.each do |user, level|
899
+ user = user.id if user.is_a? User
900
+ user = MXID.new(user.to_s) unless user.is_a? MXID
901
+ raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
902
+
903
+ if level.nil?
904
+ data[:users].delete(user.to_s.to_sym)
905
+ else
906
+ data[:users][user.to_s.to_sym] = level
907
+ end
908
+ end
817
909
  end
818
910
 
819
911
  client.api.set_power_levels(id, data)
@@ -846,10 +938,14 @@ module MatrixSdk
846
938
  private
847
939
 
848
940
  def ensure_member(member)
941
+ return unless client.cache == :all
942
+
849
943
  tinycache_adapter.write(:joined_members, []) unless tinycache_adapter.exist? :joined_members
850
944
 
851
945
  members = tinycache_adapter.read(:joined_members) || []
852
946
  members << member unless members.any? { |m| m.id == member.id }
947
+
948
+ tinycache_adapter.write(:joined_members, members)
853
949
  end
854
950
 
855
951
  def handle_power_levels(event)
@@ -857,27 +953,27 @@ module MatrixSdk
857
953
  end
858
954
 
859
955
  def handle_room_name(event)
860
- tinycache_adapter.write(:name, event[:content][:name])
956
+ tinycache_adapter.write(:name, event.dig(*%i[content name]))
861
957
  end
862
958
 
863
959
  def handle_room_topic(event)
864
- tinycache_adapter.write(:topic, event[:content][:topic])
960
+ tinycache_adapter.write(:topic, event.dig(*%i[content topic]))
865
961
  end
866
962
 
867
963
  def handle_room_guest_access(event)
868
- tinycache_adapter.write(:guest_access, event[:content][:guest_access].to_sym)
964
+ tinycache_adapter.write(:guest_access, event.dig(*%i[content guest_access])&.to_sym)
869
965
  end
870
966
 
871
967
  def handle_room_join_rules(event)
872
- tinycache_adapter.write(:join_rule, event[:content][:join_rule].to_sym)
968
+ tinycache_adapter.write(:join_rule, event.dig(*%i[content join_rule])&.to_sym)
873
969
  end
874
970
 
875
971
  def handle_room_member(event)
876
972
  return unless client.cache == :all
877
973
 
878
- if event[:content][:membership] == 'join'
974
+ if event.dig(*%i[content membership]) == 'join'
879
975
  ensure_member(client.get_user(event[:state_key]).dup.tap do |u|
880
- u.instance_variable_set :@display_name, event[:content][:displayname]
976
+ u.instance_variable_set(:@display_name, event.dig(*%i[content displayname]))
881
977
  end)
882
978
  elsif tinycache_adapter.exist? :joined_members
883
979
  members = tinycache_adapter.read(:joined_members)
@@ -886,20 +982,12 @@ module MatrixSdk
886
982
  end
887
983
 
888
984
  def handle_room_canonical_alias(event)
889
- canonical_alias = tinycache_adapter.write :canonical_alias, event[:content][:alias]
985
+ canonical_alias = tinycache_adapter.write(:canonical_alias, event.dig(*%i[content alias]))
890
986
 
891
987
  data = tinycache_adapter.read(:aliases) || []
892
988
  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)
989
+ data += event.dig(*%i[content alt_aliases]) || []
990
+ tinycache_adapter.write(:aliases, data.uniq.sort)
903
991
  end
904
992
 
905
993
  def room_handlers?
@@ -908,6 +996,7 @@ module MatrixSdk
908
996
 
909
997
  def ensure_room_handlers
910
998
  client.instance_variable_get(:@room_handlers)[id] ||= {
999
+ account_data: MatrixSdk::EventHandlerArray.new,
911
1000
  event: MatrixSdk::EventHandlerArray.new,
912
1001
  state_event: MatrixSdk::EventHandlerArray.new,
913
1002
  ephemeral_event: MatrixSdk::EventHandlerArray.new
@@ -915,7 +1004,6 @@ module MatrixSdk
915
1004
  end
916
1005
 
917
1006
  INTERNAL_HANDLERS = {
918
- 'm.room.aliases' => :handle_room_aliases,
919
1007
  'm.room.canonical_alias' => :handle_room_canonical_alias,
920
1008
  'm.room.guest_access' => :handle_room_guest_access,
921
1009
  'm.room.join_rules' => :handle_room_join_rules,
@@ -924,6 +1012,7 @@ module MatrixSdk
924
1012
  'm.room.power_levels' => :handle_power_levels,
925
1013
  'm.room.topic' => :handle_room_topic
926
1014
  }.freeze
1015
+
927
1016
  def put_event(event)
928
1017
  ensure_room_handlers[:event].fire(MatrixEvent.new(self, event), event[:type]) if room_handlers?
929
1018
 
@@ -931,6 +1020,17 @@ module MatrixSdk
931
1020
  @events.shift if @events.length > @event_history_limit
932
1021
  end
933
1022
 
1023
+ def put_account_data(event)
1024
+ if client.cache != :none
1025
+ adapter = account_data.tinycache_adapter
1026
+ adapter.write(event[:type], event[:content], expires_in: account_data.cache_time)
1027
+ end
1028
+
1029
+ return unless room_handlers?
1030
+
1031
+ ensure_room_handlers[:account_data].fire(MatrixEvent.new(self, event))
1032
+ end
1033
+
934
1034
  def put_ephemeral_event(event)
935
1035
  return unless room_handlers?
936
1036
 
@@ -6,12 +6,12 @@ module MatrixSdk::Rooms
6
6
 
7
7
  def tree(suggested_only: nil, max_rooms: nil)
8
8
  begin
9
- data = client.api.request :get, :client_unstable, "/org.matrix.msc2946/rooms/#{id}/spaces", query: {
9
+ data = client.api.request :get, :client_r0, "/rooms/#{id}/spaces", query: {
10
10
  suggested_only: suggested_only,
11
11
  max_rooms_per_space: max_rooms
12
12
  }.compact
13
- rescue
14
- data = client.api.request :get, :client_r0, "/rooms/#{id}/spaces", query: {
13
+ rescue MatrixRequestError
14
+ data = client.api.request :get, :client_unstable, "/org.matrix.msc2946/rooms/#{id}/spaces", query: {
15
15
  suggested_only: suggested_only,
16
16
  max_rooms_per_space: max_rooms
17
17
  }.compact
@@ -28,6 +28,12 @@ module MatrixSdk
28
28
  end
29
29
  end
30
30
 
31
+ def to_s
32
+ "#{display_name} (#{id})" if @display_name
33
+
34
+ @id.to_s
35
+ end
36
+
31
37
  # @return [String] the display name
32
38
  # @see MatrixSdk::Protocols::CS#get_display_name
33
39
  def display_name
@@ -68,13 +74,29 @@ module MatrixSdk
68
74
  @avatar_url = url
69
75
  end
70
76
 
77
+ # Check if the user is an admin in a given room
78
+ #
79
+ # @param room [String,MXID] the room to check
80
+ # @return [Boolean] If the user is an admin (PL >= 100)
81
+ def admin?(room)
82
+ client.ensure_room(room).user_powerlevel(self) >= 100
83
+ end
84
+
85
+ # Check if the user is a moderator in a given room
86
+ #
87
+ # @param room [String,MXID] the room to check
88
+ # @return [Boolean] If the user is an admin (PL >= 50)
89
+ def moderator?(room)
90
+ client.ensure_room(room).user_powerlevel(self) >= 50
91
+ end
92
+
71
93
  # Get the user's current presence status
72
94
  #
73
95
  # @return [Symbol] One of :online, :offline, :unavailable
74
96
  # @see MatrixSdk::Protocols::CS#get_presence_status
75
97
  # @note This information is not cached in the abstraction layer
76
98
  def presence
77
- raw_presence[:presence].to_sym
99
+ raw_presence[:presence]&.to_sym
78
100
  end
79
101
 
80
102
  # Sets the user's current presence status
@@ -132,8 +154,8 @@ module MatrixSdk
132
154
 
133
155
  # Returns all the current device keys for the user, retrieving them if necessary
134
156
  def device_keys
135
- @device_keys ||= client.api.keys_query(device_keys: { id => [] }).yield_self do |resp|
136
- resp[:device_keys][id.to_sym]
157
+ @device_keys ||= client.api.keys_query(device_keys: { id => [] }).yield_self do |resp| # rubocop:disable Style/ObjectThen # Keep Ruby 2.5 support a little longer
158
+ resp.dig(:device_keys, id.to_sym)
137
159
  end
138
160
  end
139
161
 
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MatrixSdk::Util
4
+ class AccountDataCache
5
+ extend MatrixSdk::Extensions
6
+ extend MatrixSdk::Util::Tinycache
7
+ include Enumerable
8
+
9
+ attr_reader :client, :room
10
+
11
+ attr_accessor :cache_time
12
+
13
+ ignore_inspect :client, :room, :tinycache_adapter
14
+
15
+ def initialize(client, room: nil, cache_time: 1 * 60 * 60, **_params)
16
+ raise ArgumentError, 'Must be given a Client instance' unless client.is_a? MatrixSdk::Client
17
+
18
+ @client = client
19
+ @cache_time = cache_time
20
+
21
+ return unless room
22
+
23
+ @room = room
24
+ @room = client.ensure_room room unless @room.is_a? MatrixSdk::Room
25
+ end
26
+
27
+ def reload!
28
+ tinycache_adapter.clear
29
+ end
30
+
31
+ def keys
32
+ tinycache_adapter.send(:cache).keys
33
+ end
34
+
35
+ def values
36
+ keys.map { |key| tinycache_adapter.read(key) }
37
+ end
38
+
39
+ def size
40
+ keys.count
41
+ end
42
+
43
+ def key?(key)
44
+ keys.key?(key.to_s)
45
+ end
46
+
47
+ def each(live: false)
48
+ return to_enum(__method__, live: live) { keys.count } unless block_given?
49
+
50
+ keys.each do |key|
51
+ v = live ? self[key] : tinycache_adapter.read(key)
52
+ # hash = v.hash
53
+ yield key, v
54
+ # self[key] = v if hash != v.hash
55
+ end
56
+ end
57
+
58
+ def delete(key)
59
+ key = key.to_s unless key.is_a? String
60
+ if room
61
+ client.api.set_room_account_data(client.mxid, room.id, key, {})
62
+ else
63
+ client.api.set_account_data(client.mxid, key, {})
64
+ end
65
+ tinycache_adapter.delete(key)
66
+ end
67
+
68
+ def [](key)
69
+ key = key.to_s unless key.is_a? String
70
+ tinycache_adapter.fetch(key, expires_in: @cache_time) do
71
+ if room
72
+ client.api.get_room_account_data(client.mxid, room.id, key)
73
+ else
74
+ client.api.get_account_data(client.mxid, key)
75
+ end
76
+ rescue MatrixSdk::MatrixNotFoundError
77
+ {}
78
+ end
79
+ end
80
+
81
+ def []=(key, value)
82
+ key = key.to_s unless key.is_a? String
83
+ if room
84
+ client.api.set_room_account_data(client.mxid, room.id, key, value)
85
+ else
86
+ client.api.set_account_data(client.mxid, key, value)
87
+ end
88
+ tinycache_adapter.write(key, value)
89
+ end
90
+ end
91
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pp'
4
+
3
5
  unless Object.respond_to? :yield_self
4
6
  class Object
5
7
  def yield_self
@@ -51,21 +53,29 @@ module MatrixSdk
51
53
 
52
54
  def ignore_inspect(*symbols)
53
55
  class_eval %*
54
- def inspect
55
- reentrant = caller_locations.any? { |l| l.absolute_path == __FILE__ && l.label == 'inspect' }
56
- "\\\#<\#{self.class} \#{instance_variables
56
+ include PP::ObjectMixin
57
+
58
+ def pretty_print_instance_variables
59
+ instance_variables
57
60
  .reject { |f| %i[#{symbols.map { |s| "@#{s}" }.join ' '}].include? f }
58
- .map { |f| "\#{f}=\#{reentrant ? instance_variable_get(f) : instance_variable_get(f).inspect}" }.join " " }}>"
61
+ .sort
59
62
  end
60
- *, __FILE__, __LINE__ - 7
63
+
64
+ def pretty_print(pp)
65
+ pp.pp(self)
66
+ end
67
+
68
+ alias inspect pretty_print_inspect
69
+ *, __FILE__, __LINE__ - 14
61
70
  end
62
71
  end
63
72
 
64
73
  module Logging
65
74
  def logger
66
75
  return MatrixSdk.logger if MatrixSdk.global_logger?
76
+ return @logger if instance_variable_defined?(:@logger) && @logger
67
77
 
68
- @logger ||= ::Logging.logger[self]
78
+ ::Logging.logger[self]
69
79
  end
70
80
 
71
81
  def logger=(logger)
@@ -62,7 +62,7 @@ module MatrixSdk::Util
62
62
  method_names = build_method_names(method_name)
63
63
  tinycache_adapter_config[method_name] = {
64
64
  level: cache_level,
65
- expires: expires_in || 1 * 365 * 24 * 60 * 60 # 1 year
65
+ expires: expires_in || (1 * 365 * 24 * 60 * 60) # 1 year
66
66
  }
67
67
 
68
68
  helper = const_get(cache_helper_module_name)
@@ -75,13 +75,25 @@ module MatrixSdk::Util
75
75
 
76
76
  define_method(method_names[:with_cache]) do |*args|
77
77
  tinycache_adapter.fetch(__send__(method_names[:cache_key], *args), expires_in: expires_in) do
78
- __send__(method_names[:without_cache], *args)
78
+ named = args.delete_at(-1) if args.last.is_a? Hash
79
+
80
+ if named
81
+ __send__(method_names[:without_cache], *args, **named)
82
+ else
83
+ __send__(method_names[:without_cache], *args)
84
+ end
79
85
  end
80
86
  end
81
87
 
82
88
  define_method(method_names[:without_cache]) do |*args|
83
89
  orig = method(method_name).super_method
84
- orig.call(*args)
90
+ named = args.delete_at(-1) if args.last.is_a? Hash
91
+
92
+ if named
93
+ orig.call(*args, **named)
94
+ else
95
+ orig.call(*args)
96
+ end
85
97
  end
86
98
 
87
99
  define_method(method_names[:clear_cache]) do |*args|
@@ -99,8 +111,12 @@ module MatrixSdk::Util
99
111
  define_method(method_name) do |*args|
100
112
  unless_proc = opts[:unless].is_a?(Symbol) ? opts[:unless].to_proc : opts[:unless]
101
113
 
114
+ raise ArgumentError, 'Invalid proc provided (must have arity between 1..3)' if unless_proc && !(1..3).include?(unless_proc.arity)
115
+
102
116
  skip_cache = false
103
- skip_cache ||= unless_proc&.call(self, method_name, args)
117
+ skip_cache ||= unless_proc.call(self, method_name, args) if unless_proc&.arity == 3
118
+ skip_cache ||= unless_proc.call(method_name, args) if unless_proc&.arity == 2
119
+ skip_cache ||= unless_proc.call(args) if unless_proc&.arity == 1
104
120
  skip_cache ||= CACHE_LEVELS[client&.cache || :all] < CACHE_LEVELS[cache_level]
105
121
 
106
122
  if skip_cache
@@ -2,8 +2,12 @@
2
2
 
3
3
  module MatrixSdk::Util
4
4
  class TinycacheAdapter
5
+ extend MatrixSdk::Extensions
6
+
5
7
  attr_accessor :config, :client
6
8
 
9
+ ignore_inspect :client
10
+
7
11
  def initialize
8
12
  @config = {}
9
13
 
@@ -59,7 +63,7 @@ module MatrixSdk::Util
59
63
  end
60
64
 
61
65
  def cleanup
62
- @cache.delete_if { |_, v| v.expired? }
66
+ @cache.select { |_, v| v.expired? }.each { |_, v| v.value = nil }
63
67
  end
64
68
 
65
69
  private