matrix_sdk 2.1.2 → 2.4.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 +29 -0
- data/README.md +1 -1
- data/lib/matrix_sdk.rb +11 -1
- data/lib/matrix_sdk/api.rb +84 -59
- data/lib/matrix_sdk/client.rb +80 -57
- data/lib/matrix_sdk/errors.rb +4 -0
- data/lib/matrix_sdk/mxid.rb +50 -15
- data/lib/matrix_sdk/protocols/cs.rb +61 -37
- data/lib/matrix_sdk/protocols/msc.rb +1 -1
- data/lib/matrix_sdk/response.rb +3 -1
- data/lib/matrix_sdk/room.rb +361 -112
- data/lib/matrix_sdk/rooms/space.rb +79 -0
- data/lib/matrix_sdk/user.rb +9 -1
- data/lib/matrix_sdk/util/events.rb +111 -0
- data/lib/matrix_sdk/util/extensions.rb +75 -0
- data/lib/matrix_sdk/util/tinycache.rb +130 -0
- data/lib/matrix_sdk/util/tinycache_adapter.rb +77 -0
- data/lib/matrix_sdk/util/uri.rb +89 -0
- data/lib/matrix_sdk/version.rb +1 -1
- metadata +12 -8
- data/lib/matrix_sdk/application_service.rb +0 -212
- data/lib/matrix_sdk/extensions.rb +0 -197
@@ -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
|
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'
|
data/lib/matrix_sdk/response.rb
CHANGED
data/lib/matrix_sdk/room.rb
CHANGED
@@ -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 :
|
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, :
|
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, :
|
57
|
-
|
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
|
-
@
|
81
|
+
@room_type = nil
|
102
82
|
|
103
83
|
@prev_batch = nil
|
104
84
|
|
105
85
|
data.each do |k, v|
|
106
|
-
|
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
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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::
|
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::
|
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
|
-
|
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 =
|
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 =
|
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
|
-
|
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
|
-
|
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
|