matrix_sdk 2.3.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/README.md +2 -0
- data/lib/matrix_sdk/api.rb +52 -18
- data/lib/matrix_sdk/client.rb +41 -27
- data/lib/matrix_sdk/mxid.rb +41 -1
- data/lib/matrix_sdk/protocols/cs.rb +134 -108
- data/lib/matrix_sdk/protocols/msc.rb +5 -0
- data/lib/matrix_sdk/room.rb +106 -39
- data/lib/matrix_sdk/rooms/space.rb +79 -0
- data/lib/matrix_sdk/user.rb +4 -4
- data/lib/matrix_sdk/util/events.rb +4 -6
- data/lib/matrix_sdk/util/extensions.rb +13 -19
- data/lib/matrix_sdk/util/tinycache.rb +31 -7
- data/lib/matrix_sdk/util/tinycache_adapter.rb +5 -0
- data/lib/matrix_sdk/util/uri.rb +101 -0
- data/lib/matrix_sdk/version.rb +1 -1
- data/lib/matrix_sdk.rb +10 -0
- metadata +5 -3
@@ -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
|
|
data/lib/matrix_sdk/room.rb
CHANGED
@@ -28,12 +28,14 @@ module MatrixSdk
|
|
28
28
|
# An inspect method that skips a handful of instance variables to avoid
|
29
29
|
# flooding the terminal with debug data.
|
30
30
|
# @return [String] a regular inspect string without the data for some variables
|
31
|
-
ignore_inspect :client, :events, :prev_batch, :logger
|
31
|
+
ignore_inspect :client, :events, :prev_batch, :logger, :tinycache_adapter
|
32
32
|
|
33
33
|
# Requires heavy lookups, so they're cached for an hour
|
34
|
-
cached :joined_members,
|
35
|
-
|
36
|
-
|
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
|
@@ -63,6 +65,13 @@ module MatrixSdk
|
|
63
65
|
# @option data [String,URI] :avatar_url The avatar URL for the room
|
64
66
|
# @option data [String] :prev_batch The previous batch token for backfill
|
65
67
|
def initialize(client, room_id, data = {})
|
68
|
+
if client.is_a? Room
|
69
|
+
copy = client
|
70
|
+
client = copy.client
|
71
|
+
room_id = copy.id
|
72
|
+
# data = copy.attributes
|
73
|
+
end
|
74
|
+
|
66
75
|
raise ArgumentError, 'Must be given a Client instance' unless client.is_a? Client
|
67
76
|
|
68
77
|
@client = client
|
@@ -71,6 +80,7 @@ module MatrixSdk
|
|
71
80
|
|
72
81
|
@events = []
|
73
82
|
@event_history_limit = 10
|
83
|
+
@room_type = nil
|
74
84
|
|
75
85
|
@prev_batch = nil
|
76
86
|
|
@@ -89,6 +99,24 @@ module MatrixSdk
|
|
89
99
|
logger.debug "Created room #{room_id}"
|
90
100
|
end
|
91
101
|
|
102
|
+
#
|
103
|
+
# Casting operators
|
104
|
+
#
|
105
|
+
|
106
|
+
def to_space
|
107
|
+
return nil unless space?
|
108
|
+
|
109
|
+
Rooms::Space.new self, nil
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_s
|
113
|
+
prefix = canonical_alias if canonical_alias_has_value?
|
114
|
+
prefix ||= id
|
115
|
+
return "#{prefix} | #{name}" if name_has_value?
|
116
|
+
|
117
|
+
prefix
|
118
|
+
end
|
119
|
+
|
92
120
|
#
|
93
121
|
# Event handlers
|
94
122
|
#
|
@@ -204,14 +232,14 @@ module MatrixSdk
|
|
204
232
|
#
|
205
233
|
# @return [:can_join,:forbidden] The current guest access right
|
206
234
|
def guest_access
|
207
|
-
client.api.get_room_guest_access(id)[:guest_access]
|
235
|
+
client.api.get_room_guest_access(id)[:guest_access]&.to_sym
|
208
236
|
end
|
209
237
|
|
210
238
|
# Gets the join rule for the room
|
211
239
|
#
|
212
240
|
# @return [:public,:knock,:invite,:private] The current join rule
|
213
241
|
def join_rule
|
214
|
-
client.api.get_room_join_rules(id)[:join_rule]
|
242
|
+
client.api.get_room_join_rules(id)[:join_rule]&.to_sym
|
215
243
|
end
|
216
244
|
|
217
245
|
# Checks if +guest_access+ is set to +:can_join+
|
@@ -224,11 +252,16 @@ module MatrixSdk
|
|
224
252
|
join_rule == :invite
|
225
253
|
end
|
226
254
|
|
255
|
+
# Checks if +join_rule+ is set to +:knock+
|
256
|
+
def knock_only?
|
257
|
+
join_rule == :knock
|
258
|
+
end
|
259
|
+
|
227
260
|
# Gets the history visibility of the room
|
228
261
|
#
|
229
262
|
# @return [:invited,:joined,:shared,:world_readable] The current history visibility for the room
|
230
263
|
def history_visibility
|
231
|
-
client.api.get_room_state(id, 'm.room.history_visibility')[:history_visibility]
|
264
|
+
client.api.get_room_state(id, 'm.room.history_visibility')[:history_visibility]&.to_sym
|
232
265
|
end
|
233
266
|
|
234
267
|
# Checks if the room history is world readable
|
@@ -241,15 +274,14 @@ module MatrixSdk
|
|
241
274
|
|
242
275
|
# Gets the room aliases
|
243
276
|
#
|
277
|
+
# @param canonical_only [Boolean] Should the list of aliases only contain the canonical ones
|
244
278
|
# @return [Array[String]] The assigned room aliases
|
245
|
-
def aliases
|
246
|
-
client.api.
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
.flatten
|
252
|
-
.compact
|
279
|
+
def aliases(canonical_only: true)
|
280
|
+
canonical = client.api.get_room_state(id, 'm.room.canonical_alias') rescue {}
|
281
|
+
aliases = ([canonical[:alias]].compact + (canonical[:alt_aliases] || [])).uniq.sort
|
282
|
+
return aliases if canonical_only
|
283
|
+
|
284
|
+
(aliases + client.api.get_room_aliases(id).aliases).uniq.sort
|
253
285
|
end
|
254
286
|
|
255
287
|
#
|
@@ -499,6 +531,41 @@ module MatrixSdk
|
|
499
531
|
true
|
500
532
|
end
|
501
533
|
|
534
|
+
# Gets the room creation information
|
535
|
+
#
|
536
|
+
# @return [Response] The content of the m.room.create event
|
537
|
+
def creation_info
|
538
|
+
# Not caching here, easier to cache the important values separately instead
|
539
|
+
client.api.get_room_creation_info(id)
|
540
|
+
end
|
541
|
+
|
542
|
+
# Retrieves the type of the room
|
543
|
+
#
|
544
|
+
# @return ['m.space',String,nil] The type of the room
|
545
|
+
def room_type
|
546
|
+
# Can't change, so a permanent cache is ok
|
547
|
+
return @room_type if @room_type_retrieved || @room_type
|
548
|
+
|
549
|
+
@room_type_retrieved = true
|
550
|
+
@room_type ||= creation_info[:type]
|
551
|
+
end
|
552
|
+
|
553
|
+
# Retrieves the room version
|
554
|
+
#
|
555
|
+
# @return [String] The version of the room
|
556
|
+
def room_version
|
557
|
+
@room_version ||= creation_info[:room_version]
|
558
|
+
end
|
559
|
+
|
560
|
+
# Checks if the room is a Matrix Space
|
561
|
+
#
|
562
|
+
# @return [Boolean,nil] True if the room is a space
|
563
|
+
def space?
|
564
|
+
room_type == 'm.space'
|
565
|
+
rescue MatrixSdk::MatrixForbiddenError, MatrixSdk::MatrixNotFoundError
|
566
|
+
nil
|
567
|
+
end
|
568
|
+
|
502
569
|
# Returns a list of the room tags
|
503
570
|
#
|
504
571
|
# @return [Response] A list of the tags and their data, with add and remove methods implemented
|
@@ -646,10 +713,10 @@ module MatrixSdk
|
|
646
713
|
|
647
714
|
# Sets a new avatar URL for the room
|
648
715
|
#
|
649
|
-
# @param avatar_url [URI::
|
716
|
+
# @param avatar_url [URI::MXC] The mxc:// URL for the new room avatar
|
650
717
|
def avatar_url=(avatar_url)
|
651
718
|
avatar_url = URI(avatar_url) unless avatar_url.is_a? URI
|
652
|
-
raise ArgumentError, 'Must be a valid MXC URL' unless avatar_url.is_a? URI::
|
719
|
+
raise ArgumentError, 'Must be a valid MXC URL' unless avatar_url.is_a? URI::MXC
|
653
720
|
|
654
721
|
client.api.set_room_avatar(id, avatar_url)
|
655
722
|
tinycache_adapter.write(:avatar_url, avatar_url)
|
@@ -676,7 +743,7 @@ module MatrixSdk
|
|
676
743
|
user = MXID.new(user.to_s) unless user.is_a? MXID
|
677
744
|
raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
|
678
745
|
|
679
|
-
level = power_levels
|
746
|
+
level = power_levels.dig(:users, user.to_s.to_sym)
|
680
747
|
level = power_levels[:users_default] || 0 if level.nil? && use_default
|
681
748
|
level
|
682
749
|
end
|
@@ -751,8 +818,17 @@ module MatrixSdk
|
|
751
818
|
|
752
819
|
if users
|
753
820
|
data[:users] = {} unless data.key? :users
|
754
|
-
|
755
|
-
|
821
|
+
users.each do |user, level|
|
822
|
+
user = user.id if user.is_a? User
|
823
|
+
user = MXID.new(user.to_s) unless user.is_a? MXID
|
824
|
+
raise ArgumentError, 'Must provide a valid user or MXID' unless user.user?
|
825
|
+
|
826
|
+
if level.nil?
|
827
|
+
data[:users].delete(user.to_s.to_sym)
|
828
|
+
else
|
829
|
+
data[:users][user.to_s.to_sym] = level
|
830
|
+
end
|
831
|
+
end
|
756
832
|
end
|
757
833
|
|
758
834
|
client.api.set_power_levels(id, data)
|
@@ -796,27 +872,27 @@ module MatrixSdk
|
|
796
872
|
end
|
797
873
|
|
798
874
|
def handle_room_name(event)
|
799
|
-
tinycache_adapter.write(:name, event[
|
875
|
+
tinycache_adapter.write(:name, event.dig(*%i[content name]))
|
800
876
|
end
|
801
877
|
|
802
878
|
def handle_room_topic(event)
|
803
|
-
tinycache_adapter.write(:topic, event[
|
879
|
+
tinycache_adapter.write(:topic, event.dig(*%i[content topic]))
|
804
880
|
end
|
805
881
|
|
806
882
|
def handle_room_guest_access(event)
|
807
|
-
tinycache_adapter.write(:guest_access, event[
|
883
|
+
tinycache_adapter.write(:guest_access, event.dig(*%i[content guest_access])&.to_sym)
|
808
884
|
end
|
809
885
|
|
810
886
|
def handle_room_join_rules(event)
|
811
|
-
tinycache_adapter.write(:join_rule, event[
|
887
|
+
tinycache_adapter.write(:join_rule, event.dig(*%i[content join_rule])&.to_sym)
|
812
888
|
end
|
813
889
|
|
814
890
|
def handle_room_member(event)
|
815
891
|
return unless client.cache == :all
|
816
892
|
|
817
|
-
if event[
|
893
|
+
if event.dig(*%i[content membership]) == 'join'
|
818
894
|
ensure_member(client.get_user(event[:state_key]).dup.tap do |u|
|
819
|
-
u.instance_variable_set
|
895
|
+
u.instance_variable_set(:@display_name, event.dig(*%i[content displayname]))
|
820
896
|
end)
|
821
897
|
elsif tinycache_adapter.exist? :joined_members
|
822
898
|
members = tinycache_adapter.read(:joined_members)
|
@@ -825,20 +901,12 @@ module MatrixSdk
|
|
825
901
|
end
|
826
902
|
|
827
903
|
def handle_room_canonical_alias(event)
|
828
|
-
canonical_alias = tinycache_adapter.write
|
904
|
+
canonical_alias = tinycache_adapter.write(:canonical_alias, event.dig(*%i[content alias]))
|
829
905
|
|
830
906
|
data = tinycache_adapter.read(:aliases) || []
|
831
907
|
data << canonical_alias
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
def handle_room_aliases(event)
|
836
|
-
tinycache_adapter.write(:aliases, []) unless tinycache_adapter.exist? :aliases
|
837
|
-
|
838
|
-
aliases = tinycache_adapter.read(:aliases) || []
|
839
|
-
aliases.concat event[:content][:aliases]
|
840
|
-
|
841
|
-
tinycache_adapter.write(:aliases, aliases)
|
908
|
+
data += event.dig(*%i[content alt_aliases]) || []
|
909
|
+
tinycache_adapter.write(:aliases, data.uniq.sort)
|
842
910
|
end
|
843
911
|
|
844
912
|
def room_handlers?
|
@@ -854,7 +922,6 @@ module MatrixSdk
|
|
854
922
|
end
|
855
923
|
|
856
924
|
INTERNAL_HANDLERS = {
|
857
|
-
'm.room.aliases' => :handle_room_aliases,
|
858
925
|
'm.room.canonical_alias' => :handle_room_canonical_alias,
|
859
926
|
'm.room.guest_access' => :handle_room_guest_access,
|
860
927
|
'm.room.join_rules' => :handle_room_join_rules,
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MatrixSdk::Rooms
|
4
|
+
class Space < MatrixSdk::Room
|
5
|
+
TYPE = 'm.space'
|
6
|
+
|
7
|
+
def tree(suggested_only: nil, max_rooms: nil)
|
8
|
+
begin
|
9
|
+
data = client.api.request :get, :client_r0, "/rooms/#{id}/spaces", query: {
|
10
|
+
suggested_only: suggested_only,
|
11
|
+
max_rooms_per_space: max_rooms
|
12
|
+
}.compact
|
13
|
+
rescue MatrixRequestError
|
14
|
+
data = client.api.request :get, :client_unstable, "/org.matrix.msc2946/rooms/#{id}/spaces", query: {
|
15
|
+
suggested_only: suggested_only,
|
16
|
+
max_rooms_per_space: max_rooms
|
17
|
+
}.compact
|
18
|
+
end
|
19
|
+
|
20
|
+
rooms = data.rooms.map do |r|
|
21
|
+
next if r[:room_id] == id
|
22
|
+
|
23
|
+
room = client.ensure_room(r[:room_id])
|
24
|
+
room.instance_variable_set :@room_type, r[:room_type] if r.key? :room_type
|
25
|
+
room = room.to_space if room.space?
|
26
|
+
|
27
|
+
# Inject available room information
|
28
|
+
r.each do |k, v|
|
29
|
+
if room.respond_to?("#{k}_cached?".to_sym) && send("#{k}_cached?".to_sym)
|
30
|
+
room.send(:tinycache_adapter).write(k, v)
|
31
|
+
elsif room.instance_variable_defined? "@#{k}"
|
32
|
+
room.instance_variable_set("@#{k}", v)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
room
|
36
|
+
end
|
37
|
+
rooms.compact!
|
38
|
+
|
39
|
+
grouping = {}
|
40
|
+
data.events.each do |ev|
|
41
|
+
next unless ev[:type] == 'm.space.child'
|
42
|
+
next unless ev[:content].key? :via
|
43
|
+
|
44
|
+
d = (grouping[ev[:room_id]] ||= [])
|
45
|
+
d << ev[:state_key]
|
46
|
+
end
|
47
|
+
|
48
|
+
build_tree = proc do |entry|
|
49
|
+
next if entry.nil?
|
50
|
+
|
51
|
+
room = self if entry == id
|
52
|
+
room ||= rooms.find { |r| r.id == entry }
|
53
|
+
puts "Unable to find room for entry #{entry}" unless room
|
54
|
+
# next if room.nil?
|
55
|
+
|
56
|
+
ret = {
|
57
|
+
room => []
|
58
|
+
}
|
59
|
+
|
60
|
+
grouping[entry]&.each do |child|
|
61
|
+
if grouping.key?(child)
|
62
|
+
ret[room] << build_tree.call(child)
|
63
|
+
else
|
64
|
+
child_r = self if child == id
|
65
|
+
child_r ||= rooms.find { |r| r.id == child }
|
66
|
+
|
67
|
+
ret[room] << child_r
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
ret[room].compact!
|
72
|
+
|
73
|
+
ret
|
74
|
+
end
|
75
|
+
|
76
|
+
build_tree.call(id)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/matrix_sdk/user.rb
CHANGED
@@ -59,7 +59,7 @@ module MatrixSdk
|
|
59
59
|
# Only works for the current user object, as requested by
|
60
60
|
# client.get_user(:self)
|
61
61
|
#
|
62
|
-
# @param url [String,URI::
|
62
|
+
# @param url [String,URI::MXC] the new avatar URL
|
63
63
|
# @note Requires a mxc:// URL, check example on
|
64
64
|
# {MatrixSdk::Protocols::CS#set_avatar_url} for how this can be done
|
65
65
|
# @see MatrixSdk::Protocols::CS#set_avatar_url
|
@@ -74,7 +74,7 @@ module MatrixSdk
|
|
74
74
|
# @see MatrixSdk::Protocols::CS#get_presence_status
|
75
75
|
# @note This information is not cached in the abstraction layer
|
76
76
|
def presence
|
77
|
-
raw_presence[:presence]
|
77
|
+
raw_presence[:presence]&.to_sym
|
78
78
|
end
|
79
79
|
|
80
80
|
# Sets the user's current presence status
|
@@ -132,8 +132,8 @@ module MatrixSdk
|
|
132
132
|
|
133
133
|
# Returns all the current device keys for the user, retrieving them if necessary
|
134
134
|
def device_keys
|
135
|
-
@device_keys ||= client.api.keys_query(device_keys: { id => [] }).yield_self do |resp|
|
136
|
-
resp
|
135
|
+
@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
|
136
|
+
resp.dig(:device_keys, id.to_sym)
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
@@ -22,13 +22,11 @@ module MatrixSdk
|
|
22
22
|
|
23
23
|
def fire(event, filter = nil)
|
24
24
|
reverse_each do |_k, h|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
logger.error "#{e.class.name} occurred when firing event (#{event})\n#{e}"
|
25
|
+
h[:block].call(event) if !h[:filter] || event.matches?(h[:filter], filter)
|
26
|
+
rescue StandardError => e
|
27
|
+
logger.error "#{e.class.name} occurred when firing event (#{event})\n#{e}"
|
29
28
|
|
30
|
-
|
31
|
-
end
|
29
|
+
raise e if @reraise_exceptions
|
32
30
|
end
|
33
31
|
end
|
34
32
|
end
|
@@ -1,19 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
|
5
|
-
module URI
|
6
|
-
# A mxc:// Matrix content URL
|
7
|
-
class MATRIX < Generic
|
8
|
-
def full_path
|
9
|
-
select(:host, :port, :path, :query, :fragment)
|
10
|
-
.reject(&:nil?)
|
11
|
-
.join
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
@@schemes['MXC'] = MATRIX
|
16
|
-
end
|
3
|
+
require 'pp'
|
17
4
|
|
18
5
|
unless Object.respond_to? :yield_self
|
19
6
|
class Object
|
@@ -66,13 +53,20 @@ module MatrixSdk
|
|
66
53
|
|
67
54
|
def ignore_inspect(*symbols)
|
68
55
|
class_eval %*
|
69
|
-
|
70
|
-
|
71
|
-
|
56
|
+
include PP::ObjectMixin
|
57
|
+
|
58
|
+
def pretty_print_instance_variables
|
59
|
+
instance_variables
|
72
60
|
.reject { |f| %i[#{symbols.map { |s| "@#{s}" }.join ' '}].include? f }
|
73
|
-
.
|
61
|
+
.sort
|
62
|
+
end
|
63
|
+
|
64
|
+
def pretty_print(pp)
|
65
|
+
pp.pp_object(self)
|
74
66
|
end
|
75
|
-
|
67
|
+
|
68
|
+
alias inspect pretty_print_inspect
|
69
|
+
*, __FILE__, __LINE__ - 14
|
76
70
|
end
|
77
71
|
end
|
78
72
|
|
@@ -20,7 +20,7 @@ module MatrixSdk::Util
|
|
20
20
|
|
21
21
|
def self.extended(base)
|
22
22
|
helper_name = base.send(:cache_helper_module_name)
|
23
|
-
base.remove_const
|
23
|
+
base.send :remove_const, helper_name if base.const_defined?(helper_name)
|
24
24
|
base.prepend base.const_set(helper_name, Module.new)
|
25
25
|
|
26
26
|
base.include InstanceMethods
|
@@ -62,23 +62,38 @@ 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
|
-
const_get(cache_helper_module_name)
|
68
|
+
helper = const_get(cache_helper_module_name)
|
69
|
+
return if method_names.any? { |k, _| helper.respond_to? k }
|
70
|
+
|
71
|
+
helper.class_eval do
|
69
72
|
define_method(method_names[:cache_key]) do |*args|
|
70
73
|
cache_key.call(method_name, args)
|
71
74
|
end
|
72
75
|
|
73
76
|
define_method(method_names[:with_cache]) do |*args|
|
74
77
|
tinycache_adapter.fetch(__send__(method_names[:cache_key], *args), expires_in: expires_in) do
|
75
|
-
|
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
|
76
85
|
end
|
77
86
|
end
|
78
87
|
|
79
88
|
define_method(method_names[:without_cache]) do |*args|
|
80
89
|
orig = method(method_name).super_method
|
81
|
-
|
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
|
82
97
|
end
|
83
98
|
|
84
99
|
define_method(method_names[:clear_cache]) do |*args|
|
@@ -89,11 +104,19 @@ module MatrixSdk::Util
|
|
89
104
|
true
|
90
105
|
end
|
91
106
|
|
107
|
+
define_method(method_names[:has_value]) do |*args|
|
108
|
+
tinycache_adapter.valid?(__send__(method_names[:cache_key], *args))
|
109
|
+
end
|
110
|
+
|
92
111
|
define_method(method_name) do |*args|
|
93
112
|
unless_proc = opts[:unless].is_a?(Symbol) ? opts[:unless].to_proc : opts[:unless]
|
94
113
|
|
114
|
+
raise ArgumentError, 'Invalid proc provided (must have arity between 1..3)' if unless_proc && !(1..3).include?(unless_proc.arity)
|
115
|
+
|
95
116
|
skip_cache = false
|
96
|
-
skip_cache ||= unless_proc
|
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
|
97
120
|
skip_cache ||= CACHE_LEVELS[client&.cache || :all] < CACHE_LEVELS[cache_level]
|
98
121
|
|
99
122
|
if skip_cache
|
@@ -115,7 +138,8 @@ module MatrixSdk::Util
|
|
115
138
|
with_cache: "#{method_name}_with_cache#{punctuation}",
|
116
139
|
without_cache: "#{method_name}_without_cache#{punctuation}",
|
117
140
|
clear_cache: "clear_#{method_name}_cache#{punctuation}",
|
118
|
-
cached: "#{method}_cached?"
|
141
|
+
cached: "#{method}_cached?",
|
142
|
+
has_value: "#{method}_has_value?"
|
119
143
|
}
|
120
144
|
end
|
121
145
|
end
|
@@ -16,6 +16,7 @@ module MatrixSdk::Util
|
|
16
16
|
|
17
17
|
def write(key, value, expires_in: nil, cache_level: nil)
|
18
18
|
expires_in ||= config.dig(key, :expires)
|
19
|
+
expires_in ||= 24 * 60 * 60
|
19
20
|
cache_level ||= client&.cache
|
20
21
|
cache_level ||= :all
|
21
22
|
cache_level = Tinycache::CACHE_LEVELS[cache_level] unless cache_level.is_a? Integer
|
@@ -30,6 +31,10 @@ module MatrixSdk::Util
|
|
30
31
|
cache.key?(key)
|
31
32
|
end
|
32
33
|
|
34
|
+
def valid?(key)
|
35
|
+
exist?(key) && !cache[key].expired?
|
36
|
+
end
|
37
|
+
|
33
38
|
def fetch(key, expires_in: nil, cache_level: nil, **_opts)
|
34
39
|
expires_in ||= config.dig(key, :expires)
|
35
40
|
cache_level ||= client&.cache
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module URI
|
6
|
+
# A mxc:// Matrix content URL
|
7
|
+
class MXC < Generic
|
8
|
+
def full_path
|
9
|
+
select(:host, :port, :path, :query, :fragment)
|
10
|
+
.compact
|
11
|
+
.join
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO: Use +register_scheme+ on Ruby >=3.1 and fall back to old behavior
|
16
|
+
# for older Rubies. May be removed at EOL of Ruby 3.0.
|
17
|
+
if respond_to? :register_scheme
|
18
|
+
register_scheme 'MXC', MXC
|
19
|
+
else
|
20
|
+
@@schemes['MXC'] = MXC
|
21
|
+
end
|
22
|
+
|
23
|
+
unless scheme_list.key? 'MATRIX'
|
24
|
+
# A matrix: URI according to MSC2312
|
25
|
+
class MATRIX < Generic
|
26
|
+
attr_reader :authority, :action, :mxid, :mxid2, :via
|
27
|
+
|
28
|
+
def initialize(*args)
|
29
|
+
super(*args)
|
30
|
+
|
31
|
+
@action = nil
|
32
|
+
@authority = nil
|
33
|
+
@mxid = nil
|
34
|
+
@mxid2 = nil
|
35
|
+
@via = nil
|
36
|
+
|
37
|
+
raise InvalidComponentError, 'missing opaque part for matrix URL' if !@opaque && !@path
|
38
|
+
|
39
|
+
if @path
|
40
|
+
@authority = @host
|
41
|
+
@authority += ":#{@port}" if @port
|
42
|
+
else
|
43
|
+
@path, @query = @opaque.split('?')
|
44
|
+
@query, @fragment = @query.split('#') if @query&.include? '#'
|
45
|
+
@path, @fragment = @path.split('#') if @path&.include? '#'
|
46
|
+
@path = "/#{path}"
|
47
|
+
@opaque = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
components = @path.delete_prefix('/').split('/', -1)
|
51
|
+
raise InvalidComponentError, 'component count must be 2 or 4' if components.size != 2 && components.size != 4
|
52
|
+
|
53
|
+
sigil = case components.shift
|
54
|
+
when 'u', 'user'
|
55
|
+
'@'
|
56
|
+
when 'r', 'room'
|
57
|
+
'#'
|
58
|
+
when 'roomid'
|
59
|
+
'!'
|
60
|
+
else
|
61
|
+
raise InvalidComponentError, 'invalid component in path'
|
62
|
+
end
|
63
|
+
|
64
|
+
component = components.shift
|
65
|
+
raise InvalidComponentError, "component can't be empty" if component.nil? || component.empty?
|
66
|
+
|
67
|
+
@mxid = MatrixSdk::MXID.new("#{sigil}#{component}")
|
68
|
+
|
69
|
+
if components.size == 2
|
70
|
+
sigil2 = case components.shift
|
71
|
+
when 'e', 'event'
|
72
|
+
'$'
|
73
|
+
else
|
74
|
+
raise InvalidComponentError, 'invalid component in path'
|
75
|
+
end
|
76
|
+
component = components.shift
|
77
|
+
raise InvalidComponentError, "component can't be empty" if component.nil? || component.empty?
|
78
|
+
|
79
|
+
@mxid2 = MatrixSdk::MXID.new("#{sigil2}#{component}")
|
80
|
+
end
|
81
|
+
|
82
|
+
return unless @query
|
83
|
+
|
84
|
+
@action = @query.match(/action=([^&]+)/)&.captures&.first&.to_sym
|
85
|
+
@via = @query.scan(/via=([^&]+)/)&.flatten&.compact
|
86
|
+
end
|
87
|
+
|
88
|
+
def mxid2?
|
89
|
+
!@mxid2.nil?
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# TODO: Use +register_scheme+ on Ruby >=3.1 and fall back to old behavior
|
94
|
+
# for older Rubies. May be removed at EOL of Ruby 3.0.
|
95
|
+
if respond_to? :register_scheme
|
96
|
+
register_scheme 'MATRIX', MATRIX
|
97
|
+
else
|
98
|
+
@@schemes['MATRIX'] = MATRIX
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/matrix_sdk/version.rb
CHANGED