activematrix 0.0.0 → 0.0.2
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/README.md +218 -51
- data/lib/active_matrix/agent_manager.rb +275 -0
- data/lib/active_matrix/agent_registry.rb +154 -0
- data/lib/{matrix_sdk → active_matrix}/api.rb +18 -22
- data/lib/{matrix_sdk → active_matrix}/bot/base.rb +42 -39
- data/lib/{matrix_sdk → active_matrix}/bot/main.rb +4 -5
- data/lib/active_matrix/bot/multi_instance_base.rb +189 -0
- data/lib/active_matrix/bot.rb +7 -0
- data/lib/{matrix_sdk → active_matrix}/client.rb +21 -34
- data/lib/active_matrix/client_pool.rb +194 -0
- data/lib/{matrix_sdk → active_matrix}/errors.rb +4 -4
- data/lib/active_matrix/event_router.rb +215 -0
- data/lib/active_matrix/logging.rb +56 -0
- data/lib/active_matrix/memory/agent_memory.rb +128 -0
- data/lib/active_matrix/memory/base.rb +101 -0
- data/lib/active_matrix/memory/conversation_memory.rb +161 -0
- data/lib/active_matrix/memory/global_memory.rb +153 -0
- data/lib/active_matrix/memory.rb +28 -0
- data/lib/{matrix_sdk → active_matrix}/mxid.rb +2 -2
- data/lib/{matrix_sdk → active_matrix}/protocols/as.rb +1 -1
- data/lib/{matrix_sdk → active_matrix}/protocols/cs.rb +6 -8
- data/lib/{matrix_sdk → active_matrix}/protocols/is.rb +1 -1
- data/lib/{matrix_sdk → active_matrix}/protocols/msc.rb +6 -8
- data/lib/{matrix_sdk → active_matrix}/protocols/ss.rb +2 -2
- data/lib/active_matrix/railtie.rb +18 -0
- data/lib/{matrix_sdk → active_matrix}/response.rb +2 -2
- data/lib/{matrix_sdk → active_matrix}/room.rb +148 -72
- data/lib/{matrix_sdk → active_matrix}/rooms/space.rb +3 -7
- data/lib/{matrix_sdk → active_matrix}/user.rb +23 -15
- data/lib/active_matrix/util/account_data_cache.rb +129 -0
- data/lib/active_matrix/util/cacheable.rb +73 -0
- data/lib/{matrix_sdk → active_matrix}/util/events.rb +8 -8
- data/lib/{matrix_sdk → active_matrix}/util/extensions.rb +6 -15
- data/lib/active_matrix/util/state_event_cache.rb +167 -0
- data/lib/{matrix_sdk → active_matrix}/util/uri.rb +4 -4
- data/lib/active_matrix/version.rb +5 -0
- data/lib/active_matrix.rb +81 -0
- data/lib/generators/active_matrix/bot/bot_generator.rb +38 -0
- data/lib/generators/active_matrix/bot/templates/bot.rb.erb +111 -0
- data/lib/generators/active_matrix/bot/templates/bot_spec.rb.erb +68 -0
- data/lib/generators/active_matrix/install/install_generator.rb +44 -0
- data/lib/generators/active_matrix/install/templates/README +30 -0
- data/lib/generators/active_matrix/install/templates/active_matrix.rb +33 -0
- data/lib/generators/active_matrix/install/templates/agent_memory.rb +47 -0
- data/lib/generators/active_matrix/install/templates/conversation_context.rb +72 -0
- data/lib/generators/active_matrix/install/templates/create_agent_memories.rb +17 -0
- data/lib/generators/active_matrix/install/templates/create_conversation_contexts.rb +21 -0
- data/lib/generators/active_matrix/install/templates/create_global_memories.rb +20 -0
- data/lib/generators/active_matrix/install/templates/create_matrix_agents.rb +26 -0
- data/lib/generators/active_matrix/install/templates/global_memory.rb +70 -0
- data/lib/generators/active_matrix/install/templates/matrix_agent.rb +127 -0
- metadata +168 -30
- data/lib/matrix_sdk/bot.rb +0 -4
- data/lib/matrix_sdk/util/account_data_cache.rb +0 -91
- data/lib/matrix_sdk/util/state_event_cache.rb +0 -92
- data/lib/matrix_sdk/util/tinycache.rb +0 -140
- data/lib/matrix_sdk/util/tinycache_adapter.rb +0 -87
- data/lib/matrix_sdk/version.rb +0 -5
- data/lib/matrix_sdk.rb +0 -75
@@ -1,15 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require 'matrix_sdk/util/events'
|
5
|
-
require 'matrix_sdk/util/tinycache'
|
6
|
-
|
7
|
-
module MatrixSdk
|
3
|
+
module ActiveMatrix
|
8
4
|
# A class for tracking the information about a room on Matrix
|
9
5
|
class Room
|
10
|
-
extend
|
11
|
-
|
12
|
-
include
|
6
|
+
extend ActiveMatrix::Extensions
|
7
|
+
include ActiveMatrix::Logging
|
8
|
+
include ActiveMatrix::Util::Cacheable
|
13
9
|
|
14
10
|
# @!attribute [rw] event_history_limit
|
15
11
|
# @return [Fixnum] the limit of events to keep in the event log
|
@@ -28,17 +24,9 @@ module MatrixSdk
|
|
28
24
|
# An inspect method that skips a handful of instance variables to avoid
|
29
25
|
# flooding the terminal with debug data.
|
30
26
|
# @return [String] a regular inspect string without the data for some variables
|
31
|
-
ignore_inspect :client, :events, :prev_batch, :logger
|
32
|
-
|
33
|
-
# Requires heavy lookups, so they're cached for an hour
|
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
|
27
|
+
ignore_inspect :client, :events, :prev_batch, :logger
|
39
28
|
|
40
29
|
alias room_id id
|
41
|
-
alias members joined_members
|
42
30
|
|
43
31
|
# Create a new room instance
|
44
32
|
#
|
@@ -78,23 +66,22 @@ module MatrixSdk
|
|
78
66
|
@events = []
|
79
67
|
@event_history_limit = 10
|
80
68
|
@room_type = nil
|
69
|
+
@pre_populated_members = nil # For pre-populated members from tests
|
70
|
+
@cached_joined_members = nil # Instance cache for joined members
|
71
|
+
@cached_all_members = nil # Instance cache for all members
|
81
72
|
|
82
73
|
@prev_batch = nil
|
83
74
|
|
84
75
|
%i[name topic canonical_alias avatar_url].each do |type|
|
85
|
-
room_state.
|
76
|
+
room_state.write("m.room.#{type}", { type => data.delete(type) }) if data.key? type
|
86
77
|
end
|
87
|
-
room_state.
|
88
|
-
room_state.
|
78
|
+
room_state.write('m.room.join_rules', { join_rule: data.delete(:join_rule) }) if data.key? :join_rule
|
79
|
+
room_state.write('m.room.history_visibility', { history_visibility: data.delete(:world_readable) ? :world_readable : nil }) if data.key? :world_readable
|
89
80
|
|
90
81
|
data.each do |k, v|
|
91
82
|
next if %i[client].include? k
|
92
83
|
|
93
|
-
|
94
|
-
tinycache_adapter.write(k, v)
|
95
|
-
elsif instance_variable_defined? "@#{k}"
|
96
|
-
instance_variable_set("@#{k}", v)
|
97
|
-
end
|
84
|
+
instance_variable_set("@#{k}", v) if instance_variable_defined? "@#{k}"
|
98
85
|
end
|
99
86
|
|
100
87
|
@id = room_id.to_s
|
@@ -178,7 +165,7 @@ module MatrixSdk
|
|
178
165
|
# @return [String, nil] the canonical alias of the room
|
179
166
|
def canonical_alias
|
180
167
|
get_state('m.room.canonical_alias')[:alias]
|
181
|
-
rescue
|
168
|
+
rescue ActiveMatrix::MatrixNotFoundError
|
182
169
|
nil
|
183
170
|
end
|
184
171
|
|
@@ -186,6 +173,36 @@ module MatrixSdk
|
|
186
173
|
#
|
187
174
|
# @return [Array(User)] The list of members in the room
|
188
175
|
def joined_members
|
176
|
+
# Return pre-populated members if they exist (for testing)
|
177
|
+
return @pre_populated_members if @pre_populated_members
|
178
|
+
|
179
|
+
# Return cached instance if available
|
180
|
+
return @cached_joined_members if @cached_joined_members
|
181
|
+
|
182
|
+
return fetch_joined_members unless cache_available?
|
183
|
+
|
184
|
+
# Cache the raw data that can be used to reconstruct User objects
|
185
|
+
members_data = cache.fetch(cache_key(:joined_members), expires_in: 1.hour) do
|
186
|
+
# Convert API response to cacheable format
|
187
|
+
api_response = client.api.get_room_joined_members(id)[:joined]
|
188
|
+
api_response.map do |mxid, data|
|
189
|
+
{
|
190
|
+
mxid: mxid.to_s,
|
191
|
+
display_name: data[:display_name],
|
192
|
+
avatar_url: data[:avatar_url]
|
193
|
+
}
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Reconstruct User objects from cached data and cache at instance level
|
198
|
+
@cached_joined_members = members_data.map do |member|
|
199
|
+
User.new(client, member[:mxid],
|
200
|
+
display_name: member[:display_name],
|
201
|
+
avatar_url: member[:avatar_url])
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def fetch_joined_members
|
189
206
|
client.api.get_room_joined_members(id)[:joined].map do |mxid, data|
|
190
207
|
User.new(client, mxid.to_s,
|
191
208
|
display_name: data.fetch(:display_name, nil),
|
@@ -193,6 +210,8 @@ module MatrixSdk
|
|
193
210
|
end
|
194
211
|
end
|
195
212
|
|
213
|
+
alias members joined_members
|
214
|
+
|
196
215
|
# Get all members (member events) in the room
|
197
216
|
#
|
198
217
|
# @note This will also count members who've knocked, been invited, have left, or have been banned.
|
@@ -201,6 +220,24 @@ module MatrixSdk
|
|
201
220
|
#
|
202
221
|
# @return [Array(User)] The complete list of members in the room, regardless of membership state
|
203
222
|
def all_members(**params)
|
223
|
+
# Return pre-populated members if they exist and no filtering params (for testing)
|
224
|
+
return @pre_populated_members if @pre_populated_members && params.empty?
|
225
|
+
|
226
|
+
# Return cached instance if available and no params
|
227
|
+
return @cached_all_members if @cached_all_members && params.empty?
|
228
|
+
|
229
|
+
return fetch_all_members(**params) if !params.empty? || client.cache == :none || !cache_available?
|
230
|
+
|
231
|
+
# Cache the raw member state keys, not User objects
|
232
|
+
members_data = cache.fetch(cache_key(:all_members), expires_in: 1.hour) do
|
233
|
+
client.api.get_room_members(id, **params)[:chunk].map { |ch| ch[:state_key] }
|
234
|
+
end
|
235
|
+
|
236
|
+
# Reconstruct User objects from cached data and cache at instance level
|
237
|
+
@cached_all_members = members_data.map { |state_key| client.get_user(state_key) }
|
238
|
+
end
|
239
|
+
|
240
|
+
def fetch_all_members(**params)
|
204
241
|
client.api.get_room_members(id, **params)[:chunk].map { |ch| client.get_user(ch[:state_key]) }
|
205
242
|
end
|
206
243
|
|
@@ -210,7 +247,8 @@ module MatrixSdk
|
|
210
247
|
#
|
211
248
|
# @return [String,nil] The room name - if any
|
212
249
|
def name
|
213
|
-
get_state('m.room.name')
|
250
|
+
state = get_state('m.room.name')
|
251
|
+
state&.dig(:name)
|
214
252
|
rescue MatrixNotFoundError
|
215
253
|
# No room name has been specified
|
216
254
|
nil
|
@@ -292,9 +330,9 @@ module MatrixSdk
|
|
292
330
|
end
|
293
331
|
|
294
332
|
def room_state
|
295
|
-
return
|
333
|
+
return ActiveMatrix::Util::StateEventCache.new self if client.cache == :none
|
296
334
|
|
297
|
-
@room_state ||=
|
335
|
+
@room_state ||= ActiveMatrix::Util::StateEventCache.new self
|
298
336
|
end
|
299
337
|
|
300
338
|
# Gets a state object in the room
|
@@ -327,8 +365,20 @@ module MatrixSdk
|
|
327
365
|
# @param canonical_only [Boolean] Should the list of aliases only contain the canonical ones
|
328
366
|
# @return [Array[String]] The assigned room aliases
|
329
367
|
def aliases(canonical_only: true)
|
368
|
+
return fetch_aliases(canonical_only: canonical_only) if !canonical_only || client.cache == :none || !cache_available?
|
369
|
+
|
370
|
+
cache.fetch(cache_key(:aliases), expires_in: 1.hour) do
|
371
|
+
fetch_aliases(canonical_only: true)
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
def fetch_aliases(canonical_only: true)
|
330
376
|
canonical = get_state('m.room.canonical_alias') rescue {}
|
331
|
-
|
377
|
+
# Handle both hash-like and Response objects
|
378
|
+
alias_value = canonical.respond_to?(:alias) ? canonical.alias : canonical[:alias]
|
379
|
+
alt_aliases = canonical.respond_to?(:alt_aliases) ? canonical.alt_aliases : canonical[:alt_aliases]
|
380
|
+
|
381
|
+
aliases = ([alias_value].compact + (alt_aliases || [])).uniq.sort
|
332
382
|
return aliases if canonical_only
|
333
383
|
|
334
384
|
(aliases + client.api.get_room_aliases(id).aliases).uniq.sort
|
@@ -525,7 +575,7 @@ module MatrixSdk
|
|
525
575
|
# @param user_id [String,User] the MXID of the user
|
526
576
|
# @return [Boolean] wether the action succeeded
|
527
577
|
def invite_user(user_id)
|
528
|
-
user_id = user_id.id if user_id.is_a?
|
578
|
+
user_id = user_id.id if user_id.is_a? ActiveMatrix::User
|
529
579
|
client.api.invite_user(id, user_id)
|
530
580
|
true
|
531
581
|
end
|
@@ -536,7 +586,7 @@ module MatrixSdk
|
|
536
586
|
# @param reason [String] the reason for the kick
|
537
587
|
# @return [Boolean] wether the action succeeded
|
538
588
|
def kick_user(user_id, reason = '')
|
539
|
-
user_id = user_id.id if user_id.is_a?
|
589
|
+
user_id = user_id.id if user_id.is_a? ActiveMatrix::User
|
540
590
|
client.api.kick_user(id, user_id, reason: reason)
|
541
591
|
true
|
542
592
|
end
|
@@ -547,7 +597,7 @@ module MatrixSdk
|
|
547
597
|
# @param reason [String] the reason for the ban
|
548
598
|
# @return [Boolean] wether the action succeeded
|
549
599
|
def ban_user(user_id, reason = '')
|
550
|
-
user_id = user_id.id if user_id.is_a?
|
600
|
+
user_id = user_id.id if user_id.is_a? ActiveMatrix::User
|
551
601
|
client.api.ban_user(id, user_id, reason: reason)
|
552
602
|
true
|
553
603
|
end
|
@@ -557,7 +607,7 @@ module MatrixSdk
|
|
557
607
|
# @param user_id [String,User] the MXID of the user
|
558
608
|
# @return [Boolean] wether the action succeeded
|
559
609
|
def unban_user(user_id)
|
560
|
-
user_id = user_id.id if user_id.is_a?
|
610
|
+
user_id = user_id.id if user_id.is_a? ActiveMatrix::User
|
561
611
|
client.api.unban_user(id, user_id)
|
562
612
|
true
|
563
613
|
end
|
@@ -572,9 +622,9 @@ module MatrixSdk
|
|
572
622
|
end
|
573
623
|
|
574
624
|
def account_data
|
575
|
-
return
|
625
|
+
return ActiveMatrix::Util::AccountDataCache.new client, room: self if client.cache == :none
|
576
626
|
|
577
|
-
@account_data ||=
|
627
|
+
@account_data ||= ActiveMatrix::Util::AccountDataCache.new client, room: self
|
578
628
|
end
|
579
629
|
|
580
630
|
# Retrieves a custom entry from the room-specific account data
|
@@ -640,7 +690,7 @@ module MatrixSdk
|
|
640
690
|
# @return [Boolean,nil] True if the room is a space
|
641
691
|
def space?
|
642
692
|
room_type == 'm.space'
|
643
|
-
rescue
|
693
|
+
rescue ActiveMatrix::MatrixForbiddenError, ActiveMatrix::MatrixNotFoundError
|
644
694
|
nil
|
645
695
|
end
|
646
696
|
|
@@ -739,7 +789,8 @@ module MatrixSdk
|
|
739
789
|
# @return [Boolean] if the addition was successful or not
|
740
790
|
def add_alias(room_alias)
|
741
791
|
client.api.set_room_alias(id, room_alias)
|
742
|
-
|
792
|
+
# Clear the cache to force refresh
|
793
|
+
cache.delete(cache_key(:aliases)) if cache_available?
|
743
794
|
true
|
744
795
|
end
|
745
796
|
|
@@ -750,7 +801,7 @@ module MatrixSdk
|
|
750
801
|
# alias list updates.
|
751
802
|
def reload_aliases!
|
752
803
|
room_state.expire('m.room.canonical_alias')
|
753
|
-
|
804
|
+
cache.delete(cache_key(:aliases)) if cache_available?
|
754
805
|
end
|
755
806
|
alias refresh_aliases! reload_aliases!
|
756
807
|
|
@@ -900,7 +951,7 @@ module MatrixSdk
|
|
900
951
|
def modify_user_power_levels(users = nil, users_default = nil)
|
901
952
|
return false if users.nil? && users_default.nil?
|
902
953
|
|
903
|
-
room_state.
|
954
|
+
room_state.expire 'm.room.power_levels'
|
904
955
|
|
905
956
|
data = power_levels
|
906
957
|
data[:users_default] = users_default unless users_default.nil?
|
@@ -932,7 +983,7 @@ module MatrixSdk
|
|
932
983
|
def modify_required_power_levels(events = nil, params = {})
|
933
984
|
return false if events.nil? && (params.nil? || params.empty?)
|
934
985
|
|
935
|
-
room_state.
|
986
|
+
room_state.expire 'm.room.power_levels'
|
936
987
|
|
937
988
|
data = power_levels
|
938
989
|
data.merge!(params)
|
@@ -950,38 +1001,52 @@ module MatrixSdk
|
|
950
1001
|
|
951
1002
|
private
|
952
1003
|
|
1004
|
+
def cache_key(method_name)
|
1005
|
+
"activematrix:room:#{id}:#{method_name}"
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
def cache_available?
|
1009
|
+
defined?(::Rails) && ::Rails.respond_to?(:cache) && ::Rails.cache
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
def cache
|
1013
|
+
::Rails.cache
|
1014
|
+
end
|
1015
|
+
|
953
1016
|
def ensure_member(member)
|
954
1017
|
return unless client.cache == :all
|
955
1018
|
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
members << member unless members.any? { |m| m.id == member.id }
|
1019
|
+
# Add member to pre-populated list
|
1020
|
+
@pre_populated_members ||= []
|
1021
|
+
@pre_populated_members << member unless @pre_populated_members.include?(member)
|
960
1022
|
|
961
|
-
|
1023
|
+
# Clear the cache to force a refresh on next access
|
1024
|
+
cache.delete(cache_key(:joined_members)) if cache_available?
|
962
1025
|
end
|
963
1026
|
|
964
1027
|
def handle_room_member(event)
|
965
1028
|
return unless client.cache == :all
|
966
1029
|
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
1030
|
+
# Cache the user if it's a join event
|
1031
|
+
client.get_user(event[:state_key]) if event.dig(:content, :membership) == 'join' && event[:state_key]
|
1032
|
+
|
1033
|
+
# Clear pre-populated members when membership changes
|
1034
|
+
@pre_populated_members = nil
|
1035
|
+
|
1036
|
+
# Clear instance caches when membership changes
|
1037
|
+
@cached_joined_members = nil
|
1038
|
+
@cached_all_members = nil
|
1039
|
+
|
1040
|
+
# Clear the cache when membership changes
|
1041
|
+
cache.delete(cache_key(:joined_members)) if cache_available?
|
1042
|
+
cache.delete(cache_key(:all_members)) if cache_available?
|
975
1043
|
end
|
976
1044
|
|
977
1045
|
def handle_room_canonical_alias(event)
|
978
|
-
room_state.
|
979
|
-
canonical_alias = event.dig(*%i[content alias])
|
1046
|
+
room_state.write('m.room.canonical_alias', event[:content])
|
980
1047
|
|
981
|
-
|
982
|
-
|
983
|
-
data += event.dig(*%i[content alt_aliases]) || []
|
984
|
-
tinycache_adapter.write(:aliases, data.uniq.sort)
|
1048
|
+
# Clear the aliases cache
|
1049
|
+
cache.delete(cache_key(:aliases)) if cache_available?
|
985
1050
|
end
|
986
1051
|
|
987
1052
|
def room_handlers?
|
@@ -990,10 +1055,10 @@ module MatrixSdk
|
|
990
1055
|
|
991
1056
|
def ensure_room_handlers
|
992
1057
|
client.instance_variable_get(:@room_handlers)[id] ||= {
|
993
|
-
account_data:
|
994
|
-
event:
|
995
|
-
state_event:
|
996
|
-
ephemeral_event:
|
1058
|
+
account_data: ActiveMatrix::EventHandlerArray.new,
|
1059
|
+
event: ActiveMatrix::EventHandlerArray.new,
|
1060
|
+
state_event: ActiveMatrix::EventHandlerArray.new,
|
1061
|
+
ephemeral_event: ActiveMatrix::EventHandlerArray.new
|
997
1062
|
}
|
998
1063
|
end
|
999
1064
|
|
@@ -1005,10 +1070,8 @@ module MatrixSdk
|
|
1005
1070
|
end
|
1006
1071
|
|
1007
1072
|
def put_account_data(event)
|
1008
|
-
|
1009
|
-
|
1010
|
-
adapter.write(event[:type], event[:content], expires_in: account_data.cache_time)
|
1011
|
-
end
|
1073
|
+
# Store the account data in cache
|
1074
|
+
account_data.write(event[:type], event[:content]) if event[:type]
|
1012
1075
|
|
1013
1076
|
return unless room_handlers?
|
1014
1077
|
|
@@ -1030,15 +1093,28 @@ module MatrixSdk
|
|
1030
1093
|
if INTERNAL_HANDLERS.key? event[:type]
|
1031
1094
|
send(INTERNAL_HANDLERS[event[:type]], event)
|
1032
1095
|
elsif client.cache != :none
|
1033
|
-
|
1034
|
-
|
1035
|
-
key += "|#{event[:state_key]}" unless event[:state_key].nil? || event[:state_key].empty?
|
1036
|
-
adapter.write(key, event[:content], expires_in: room_state.cache_time)
|
1096
|
+
# StateEventCache will handle caching internally
|
1097
|
+
room_state.write(event[:type], event[:content], event[:state_key])
|
1037
1098
|
end
|
1038
1099
|
|
1039
1100
|
return unless room_handlers?
|
1040
1101
|
|
1041
1102
|
ensure_room_handlers[:state_event].fire(MatrixEvent.new(self, event), event[:type])
|
1042
1103
|
end
|
1104
|
+
|
1105
|
+
# Define what attributes to cache
|
1106
|
+
def cache_attributes
|
1107
|
+
{
|
1108
|
+
id: @id,
|
1109
|
+
room_type: @room_type,
|
1110
|
+
prev_batch: @prev_batch,
|
1111
|
+
event_history_limit: @event_history_limit
|
1112
|
+
}
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
# Override cache_id to use room ID
|
1116
|
+
def cache_id
|
1117
|
+
@id
|
1118
|
+
end
|
1043
1119
|
end
|
1044
1120
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
4
|
-
class Space <
|
3
|
+
module ActiveMatrix::Rooms
|
4
|
+
class Space < ActiveMatrix::Room
|
5
5
|
TYPE = 'm.space'
|
6
6
|
|
7
7
|
def tree(suggested_only: nil, max_rooms: nil)
|
@@ -26,11 +26,7 @@ module MatrixSdk::Rooms
|
|
26
26
|
|
27
27
|
# Inject available room information
|
28
28
|
r.each do |k, v|
|
29
|
-
|
30
|
-
room.send(:tinycache_adapter).write(k, v)
|
31
|
-
elsif room.instance_variable_defined? "@#{k}"
|
32
|
-
room.instance_variable_set("@#{k}", v)
|
33
|
-
end
|
29
|
+
room.instance_variable_set("@#{k}", v) if room.instance_variable_defined? "@#{k}"
|
34
30
|
end
|
35
31
|
room
|
36
32
|
end
|
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
module MatrixSdk
|
3
|
+
module ActiveMatrix
|
6
4
|
# A class for tracking information about a user on Matrix
|
7
5
|
class User
|
8
|
-
extend
|
6
|
+
extend ActiveMatrix::Extensions
|
7
|
+
include ActiveMatrix::Util::Cacheable
|
9
8
|
|
10
9
|
attr_reader :id, :client
|
11
10
|
alias user_id :id
|
@@ -35,13 +34,13 @@ module MatrixSdk
|
|
35
34
|
end
|
36
35
|
|
37
36
|
# @return [String] the display name
|
38
|
-
# @see
|
37
|
+
# @see ActiveMatrix::Protocols::CS#get_display_name
|
39
38
|
def display_name
|
40
39
|
@display_name ||= client.api.get_display_name(id)[:displayname]
|
41
40
|
end
|
42
41
|
|
43
42
|
# @param name [String] the display name to set
|
44
|
-
# @see
|
43
|
+
# @see ActiveMatrix::Protocols::CS#set_display_name
|
45
44
|
def display_name=(name)
|
46
45
|
client.api.set_display_name(id, name)
|
47
46
|
@display_name = name
|
@@ -55,7 +54,7 @@ module MatrixSdk
|
|
55
54
|
|
56
55
|
# Gets the avatar for the user
|
57
56
|
#
|
58
|
-
# @see
|
57
|
+
# @see ActiveMatrix::Protocols::CS#get_avatar_url
|
59
58
|
def avatar_url
|
60
59
|
@avatar_url ||= client.api.get_avatar_url(id)[:avatar_url]
|
61
60
|
end
|
@@ -67,8 +66,8 @@ module MatrixSdk
|
|
67
66
|
#
|
68
67
|
# @param url [String,URI::MXC] the new avatar URL
|
69
68
|
# @note Requires a mxc:// URL, check example on
|
70
|
-
# {
|
71
|
-
# @see
|
69
|
+
# {ActiveMatrix::Protocols::CS#set_avatar_url} for how this can be done
|
70
|
+
# @see ActiveMatrix::Protocols::CS#set_avatar_url
|
72
71
|
def avatar_url=(url)
|
73
72
|
client.api.set_avatar_url(id, url)
|
74
73
|
@avatar_url = url
|
@@ -93,7 +92,7 @@ module MatrixSdk
|
|
93
92
|
# Get the user's current presence status
|
94
93
|
#
|
95
94
|
# @return [Symbol] One of :online, :offline, :unavailable
|
96
|
-
# @see
|
95
|
+
# @see ActiveMatrix::Protocols::CS#get_presence_status
|
97
96
|
# @note This information is not cached in the abstraction layer
|
98
97
|
def presence
|
99
98
|
raw_presence[:presence]&.to_sym
|
@@ -103,7 +102,7 @@ module MatrixSdk
|
|
103
102
|
# Should be one of :online, :offline, or :unavailable
|
104
103
|
#
|
105
104
|
# @param new_presence [:online,:offline,:unavailable] The new presence status to set
|
106
|
-
# @see
|
105
|
+
# @see ActiveMatrix::Protocols::CS#set_presence_status
|
107
106
|
def presence=(new_presence)
|
108
107
|
raise ArgumentError, 'Presence must be one of :online, :offline, :unavailable' unless %i[online offline unavailable].include?(presence)
|
109
108
|
|
@@ -118,7 +117,7 @@ module MatrixSdk
|
|
118
117
|
|
119
118
|
# Gets the user-specified status message - if any
|
120
119
|
#
|
121
|
-
# @see
|
120
|
+
# @see ActiveMatrix::Protocols::CS#get_presence_status
|
122
121
|
# @note This information is not cached in the abstraction layer
|
123
122
|
def status_msg
|
124
123
|
raw_presence[:status_msg]
|
@@ -127,7 +126,7 @@ module MatrixSdk
|
|
127
126
|
# Sets the user-specified status message
|
128
127
|
#
|
129
128
|
# @param message [String,nil] The message to set, or nil for no message
|
130
|
-
# @see
|
129
|
+
# @see ActiveMatrix::Protocols::CS#set_presence_status
|
131
130
|
def status_msg=(message)
|
132
131
|
client.api.set_presence_status(id, presence, message: message)
|
133
132
|
end
|
@@ -135,7 +134,7 @@ module MatrixSdk
|
|
135
134
|
# Gets the last time the user was active at, from the server's side
|
136
135
|
#
|
137
136
|
# @return [Time] when the user was last active
|
138
|
-
# @see
|
137
|
+
# @see ActiveMatrix::Protocols::CS#get_presence_status
|
139
138
|
# @note This information is not cached in the abstraction layer
|
140
139
|
def last_active
|
141
140
|
since = raw_presence[:last_active_ago]
|
@@ -147,7 +146,7 @@ module MatrixSdk
|
|
147
146
|
# Gets a direct message room with the user if one exists
|
148
147
|
#
|
149
148
|
# @return [Room,nil] A direct message room if one exists
|
150
|
-
# @see
|
149
|
+
# @see ActiveMatrix::Client#direct_room
|
151
150
|
def direct_room
|
152
151
|
client.direct_room(id)
|
153
152
|
end
|
@@ -159,6 +158,15 @@ module MatrixSdk
|
|
159
158
|
end
|
160
159
|
end
|
161
160
|
|
161
|
+
# Define what attributes to cache
|
162
|
+
def cache_attributes
|
163
|
+
{
|
164
|
+
id: @id,
|
165
|
+
display_name: @display_name,
|
166
|
+
avatar_url: @avatar_url
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
162
170
|
private
|
163
171
|
|
164
172
|
def raw_presence
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveMatrix::Util
|
4
|
+
class AccountDataCache
|
5
|
+
extend ActiveMatrix::Extensions
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_reader :client, :room
|
9
|
+
|
10
|
+
attr_accessor :cache_time
|
11
|
+
|
12
|
+
ignore_inspect :client, :room
|
13
|
+
|
14
|
+
def initialize(client, room: nil, cache_time: 1 * 60 * 60, **_params)
|
15
|
+
raise ArgumentError, 'Must be given a Client instance' unless client.is_a? ActiveMatrix::Client
|
16
|
+
|
17
|
+
@client = client
|
18
|
+
@cache_time = cache_time
|
19
|
+
@tracked_keys = Set.new
|
20
|
+
|
21
|
+
return unless room
|
22
|
+
|
23
|
+
@room = room
|
24
|
+
@room = client.ensure_room room unless @room.is_a? ActiveMatrix::Room
|
25
|
+
end
|
26
|
+
|
27
|
+
def reload!
|
28
|
+
# Clear all cache entries for this account data
|
29
|
+
return unless cache_available?
|
30
|
+
|
31
|
+
if room
|
32
|
+
cache.delete_matched("activematrix:account_data:#{client.mxid}:room:#{room.id}:*")
|
33
|
+
else
|
34
|
+
cache.delete_matched("activematrix:account_data:#{client.mxid}:global:*")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def keys
|
39
|
+
@tracked_keys.to_a.sort
|
40
|
+
end
|
41
|
+
|
42
|
+
def values
|
43
|
+
[]
|
44
|
+
end
|
45
|
+
|
46
|
+
def size
|
47
|
+
keys.count
|
48
|
+
end
|
49
|
+
|
50
|
+
def key?(key)
|
51
|
+
cache_available? && cache.exist?(cache_key(key))
|
52
|
+
end
|
53
|
+
|
54
|
+
def each(live: false)
|
55
|
+
to_enum(__method__, live: live) { 0 } unless block_given?
|
56
|
+
# Not enumerable with Rails.cache
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete(key)
|
60
|
+
key = key.to_s unless key.is_a? String
|
61
|
+
if room
|
62
|
+
client.api.set_room_account_data(client.mxid, room.id, key, {})
|
63
|
+
else
|
64
|
+
client.api.set_account_data(client.mxid, key, {})
|
65
|
+
end
|
66
|
+
cache.delete(cache_key(key)) if cache_available?
|
67
|
+
end
|
68
|
+
|
69
|
+
def [](key)
|
70
|
+
key = key.to_s unless key.is_a? String
|
71
|
+
|
72
|
+
# Track the key whenever it's accessed
|
73
|
+
@tracked_keys.add(key)
|
74
|
+
|
75
|
+
return fetch_account_data(key) unless cache_available?
|
76
|
+
|
77
|
+
cache.fetch(cache_key(key), expires_in: @cache_time) do
|
78
|
+
fetch_account_data(key)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def fetch_account_data(key)
|
83
|
+
if room
|
84
|
+
client.api.get_room_account_data(client.mxid, room.id, key)
|
85
|
+
else
|
86
|
+
client.api.get_account_data(client.mxid, key)
|
87
|
+
end
|
88
|
+
rescue ActiveMatrix::MatrixNotFoundError
|
89
|
+
{}
|
90
|
+
end
|
91
|
+
|
92
|
+
def []=(key, value)
|
93
|
+
key = key.to_s unless key.is_a? String
|
94
|
+
if room
|
95
|
+
client.api.set_room_account_data(client.mxid, room.id, key, value)
|
96
|
+
else
|
97
|
+
client.api.set_account_data(client.mxid, key, value)
|
98
|
+
end
|
99
|
+
|
100
|
+
@tracked_keys.add(key)
|
101
|
+
cache.write(cache_key(key), value, expires_in: @cache_time) if cache_available?
|
102
|
+
end
|
103
|
+
|
104
|
+
# Write data without making API call (for sync responses)
|
105
|
+
def write(key, value)
|
106
|
+
key = key.to_s unless key.is_a? String
|
107
|
+
@tracked_keys.add(key)
|
108
|
+
cache.write(cache_key(key), value, expires_in: @cache_time) if cache_available?
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def cache_key(key)
|
114
|
+
if room
|
115
|
+
"activematrix:account_data:#{client.mxid}:room:#{room.id}:#{key}"
|
116
|
+
else
|
117
|
+
"activematrix:account_data:#{client.mxid}:global:#{key}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def cache_available?
|
122
|
+
defined?(::Rails) && ::Rails.respond_to?(:cache) && ::Rails.cache
|
123
|
+
end
|
124
|
+
|
125
|
+
def cache
|
126
|
+
::Rails.cache
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|