matrix_sdk 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d0b5d000dfb07e1f488a66587a403c087c7056b2cde52cd2ee87e4835972a23
4
- data.tar.gz: 1fdd6f7a913b42cf8654eeed0b198d14337f47ab7da71baf43c1b2779d752eb5
3
+ metadata.gz: fc787a1c2e4bac79cf05357500571df2e7734464023a5182d08614b9e45e9aac
4
+ data.tar.gz: 465ea39af281892dcb299014b8a5b4bc0c869f6914974f40cb6fd21301090129
5
5
  SHA512:
6
- metadata.gz: 466f80ee4d8b06c1827de39e7526a23e62e654db99c2102db5552492992a58fd6f6a4883d1c90d2a577c345d67312de51d5cbdb0a2bfbcab461278141dffcbc4
7
- data.tar.gz: 189b5b6243fb574b60ac02036850bfe33f20499b4a88ea9840491892f840fd367167be5233da73e08811d6d8721523bce9027e4907ea6c927a9c70a8c1ed20cc
6
+ metadata.gz: a18893ee520aedfacc011cf5888b310875ee6929fa94967a0eeee01e91d592a56b19b190e6400e5e9338ccf477f9ac4cb1c480866fb720c1eecee7f0fb005a6f
7
+ data.tar.gz: ed1d6b9eaad9795147ffb8bf319c4fed25598147a2af2f97048eb0285684c32fc7809e36ad891917f3499105778eb11409d8577941258c9fb94cee84b4c41dbd
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,33 @@
1
+ ---
2
+ image: "ruby:2.4"
3
+
4
+ # Cache gems in between builds
5
+ cache:
6
+ paths:
7
+ - vendor/ruby
8
+
9
+ before_script:
10
+ - gem install bundler --no-ri --no-rdoc
11
+ - bundle install -j $(nproc) --path vendor
12
+
13
+ rubocop:
14
+ before_script: []
15
+ script:
16
+ - gem install rubocop --no-ri --no-rdoc
17
+ - rubocop
18
+
19
+ # rspec:
20
+ # script:
21
+ # - rspec spec
22
+
23
+ pages:
24
+ stage: deploy
25
+ before_script: []
26
+ script:
27
+ - gem install yard
28
+ - yard doc -o public/
29
+ artifacts:
30
+ paths:
31
+ - public/
32
+ only:
33
+ - master
data/.rubocop.yml CHANGED
@@ -8,6 +8,9 @@ AllCops:
8
8
  Style/Documentation:
9
9
  Enabled: false
10
10
 
11
+ Metrics/ClassLength:
12
+ Enabled: false
13
+
11
14
  Metrics/MethodLength:
12
15
  Max: 40
13
16
 
data/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ ## v0.0.3 - 2018-08-14
2
+
3
+ - Adds missing accessors for HTTP timeout
4
+ - Adds methods for checking auth status to client API
5
+ - Adds a wrapper class for API responses to ease use
6
+ - Adds option (and defaults) to store login details on registration
7
+ - Allows creating a MatrixSdk::Client off of an existing MatrixSdk::Api
8
+ - Extends event handling
9
+
10
+ - Fixes batch handling in sync
11
+ - Fixes event handling in the sample
12
+ - Removes unimplemented API methods to avoid confusion
13
+
14
+ - Plenty of documentation work
15
+
16
+ ## v0.0.2 - 2018-05-11
17
+
18
+ - Fixes for multiple issues discovered after initial release
19
+ - Adds additional API methods
20
+ - Higher-level client API gets room and user abstractions
21
+
22
+ ## v0.0.1 - 2018-05-06
23
+
24
+ Initial release
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  A Ruby gem for easing the development of software that communicates with servers implementing the Matrix protocol.
4
4
 
5
+ Live YARD documentation can be found at; http://aleol57.gitlab-pages.liu.se/ruby-matrix-sdk
5
6
 
6
7
  ## Example usage
7
8
 
@@ -11,7 +11,7 @@ class SimpleClient < MatrixSdk::Client
11
11
  end
12
12
 
13
13
  def add_listener(room)
14
- room.on_event { |ev| on_message(room, ev) }
14
+ room.on_event.add_handler { |ev| on_message(room, ev) }
15
15
  end
16
16
 
17
17
  def run
@@ -26,20 +26,22 @@ class SimpleClient < MatrixSdk::Client
26
26
  end
27
27
 
28
28
  def on_message(room, event)
29
- puts "Event: #{ev}"
30
- case ev[:type]
29
+ case event.type
31
30
  when 'm.room.member'
32
- puts "#{Time.now.strftime '%H:%M'} #{event[:content][:displayname]} joined." if event['membership'] == 'join'
31
+ puts "[#{Time.now.strftime '%H:%M'}] #{event[:content][:displayname]} joined." if event.membership == 'join'
33
32
  when 'm.room.message'
34
- user = get_user event[:sender]
35
- admin_level = get_user_level(room, user.id)
36
- prefix = (admin_level >= 100 ? '@' : (admin_level >= 50 ? '+' : ' '))
37
- if %w[m.text m.notice].include? event[:content][:msgtype]
38
- puts "#{Time.now.strftime '%H:%M'} <#{prefix}#{user.display_name}> #{event[:content][:body]}"
33
+ user = get_user event.sender
34
+ admin_level = get_user_level(room, user.id) || 0
35
+ prefix = ' '
36
+ prefix = '+' if admin_level >= 50
37
+ prefix = '@' if admin_level >= 100
38
+ if %w[m.text m.notice].include? event.content[:msgtype]
39
+ notice = event.content[:msgtype] == 'm.notice'
40
+ puts "[#{Time.now.strftime '%H:%M'}] <#{prefix}#{user.display_name}> #{"\033[1;30m" if notice}#{event.content[:body]}#{"\033[0m" if notice}"
39
41
  elsif event[:content][:msgtype] == 'm.emote'
40
- puts "#{Time.now.strftime '%H:%M'} *#{prefix}#{user.display_name} #{event[:content][:body]}"
42
+ puts "[#{Time.now.strftime '%H:%M'}] *#{prefix}#{user.display_name} #{event.content[:body]}"
41
43
  else
42
- puts "#{Time.now.strftime '%H:%M'} <#{prefix}#{user.display_name}> [#{event[:content][:msgtype]}] #{event[:content][:body]} - #{api.get_download_url event[:content][:url]}"
44
+ puts "[#{Time.now.strftime '%H:%M'}] <#{prefix}#{user.display_name}> (#{event.content[:msgtype]}) #{event.content[:body]} - #{api.get_download_url event.content[:url]}"
43
45
  end
44
46
  end
45
47
  end
@@ -54,6 +56,7 @@ if $PROGRAM_NAME == __FILE__
54
56
  end
55
57
 
56
58
  client = SimpleClient.new ARGV.first
59
+ ARGV.shift
57
60
 
58
61
  print 'Username: '
59
62
  user = STDIN.gets.strip
@@ -87,7 +90,9 @@ if $PROGRAM_NAME == __FILE__
87
90
  room.send_text msg
88
91
  end
89
92
  end
93
+ rescue Interrupt
94
+ puts 'Interrupted, exiting...'
90
95
  ensure
91
- client.logout if client
96
+ client.logout if client && client.logged_in?
92
97
  end
93
98
  end
@@ -7,14 +7,31 @@ require 'uri'
7
7
 
8
8
  module MatrixSdk
9
9
  class Api
10
- attr_accessor :access_token, :device_id
11
- attr_reader :homeserver, :validate_certificate
12
-
13
- ignore_inspect :access_token
14
-
10
+ USER_AGENT = "Ruby Matrix SDK v#{MatrixSdk::VERSION}".freeze
11
+ DEFAULT_HEADERS = {
12
+ 'accept' => 'application/json',
13
+ 'user-agent' => USER_AGENT
14
+ }.freeze
15
+
16
+ attr_accessor :access_token, :device_id, :autoretry, :global_headers
17
+ attr_reader :homeserver, :validate_certificate, :read_timeout
18
+
19
+ ignore_inspect :access_token, :logger
20
+
21
+ # @param homeserver [String,URI] The URL to the Matrix homeserver, without the /_matrix/ part
22
+ # @param params [Hash] Additional parameters on creation
23
+ # @option params [String] :access_token The access token to use for the connection
24
+ # @option params [String] :device_id The ID of the logged in decide to use
25
+ # @option params [Boolean] :autoretry (true) Should requests automatically be retried in case of rate limits
26
+ # @option params [Boolean] :validate_certificate (false) Should the connection require valid SSL certificates
27
+ # @option params [Integer] :transaction_id (0) The starting ID for transactions
28
+ # @option params [Numeric] :backoff_time (5000) The request backoff time in milliseconds
29
+ # @option params [Numeric] :read_timeout (240) The timeout in seconds for reading responses
30
+ # @option params [Hash] :global_headers Additional headers to set for all requests
31
+ # @option params [Boolean] :skip_login Should the API skip logging in if the HS URL contains user information
15
32
  def initialize(homeserver, params = {})
16
33
  @homeserver = homeserver
17
- @homeserver = URI.parse(@homeserver.to_s) unless @homeserver.is_a? URI
34
+ @homeserver = URI.parse("#{'https://' unless @homeserver.start_with? 'http'}#{@homeserver}") unless @homeserver.is_a? URI
18
35
  if @homeserver.path.end_with? '_matrix/'
19
36
  @homeserver.path = begin
20
37
  split = @homeserver.path.rpartition '_matrix/'
@@ -26,24 +43,41 @@ module MatrixSdk
26
43
 
27
44
  @access_token = params.fetch(:access_token, nil)
28
45
  @device_id = params.fetch(:device_id, nil)
46
+ @autoretry = params.fetch(:autoretry, true)
29
47
  @validate_certificate = params.fetch(:validate_certificate, false)
30
48
  @transaction_id = params.fetch(:transaction_id, 0)
31
49
  @backoff_time = params.fetch(:backoff_time, 5000)
50
+ @read_timeout = params.fetch(:read_timeout, 240)
51
+ @global_headers = DEFAULT_HEADERS.dup
52
+ @global_headers.merge!(params.fetch(:global_headers)) if params.key? :global_headers
32
53
 
33
54
  login(user: @homeserver.user, password: @homeserver.password) if @homeserver.user && @homeserver.password && !@access_token && !params[:skip_login]
34
55
  @homeserver.userinfo = '' unless params[:skip_login]
35
56
  end
36
57
 
58
+ # Gets the logger for the API
59
+ # @return [Logging::Logger] The API-scope logger
37
60
  def logger
38
- @logger ||= Logging.logger[self.class.name]
61
+ @logger ||= Logging.logger[self]
62
+ end
63
+
64
+ # @param seconds [Numeric]
65
+ # @return [Numeric]
66
+ def read_timeout=(seconds)
67
+ @http.finish if @http && @read_timeout != seconds
68
+ @read_timeout = seconds
39
69
  end
40
70
 
71
+ # @param validate [Boolean]
72
+ # @return [Boolean]
41
73
  def validate_certificate=(validate)
42
74
  # The HTTP connection needs to be reopened if this changes
43
75
  @http.finish if @http && validate != @validate_certificate
44
76
  @validate_certificate = validate
45
77
  end
46
78
 
79
+ # @param hs_info [URI]
80
+ # @return [URI]
47
81
  def homeserver=(hs_info)
48
82
  # TODO: DNS query for SRV information about HS?
49
83
  return unless hs_info.is_a? URI
@@ -51,10 +85,34 @@ module MatrixSdk
51
85
  @homeserver = hs_info
52
86
  end
53
87
 
54
- def api_versions
55
- request(:get, :client, '/versions')
88
+ # Gets the available client API versions
89
+ # @return [Array]
90
+ def client_api_versions
91
+ @client_api_versions ||= request(:get, :client, '/versions').versions
92
+ end
93
+
94
+ # Gets the server version
95
+ # @note This uses the unstable federation/v1 API
96
+ def server_version
97
+ Response.new(self, request(:get, :federation_v1, '/version').server).tap do |resp|
98
+ resp.instance_eval <<-'CODE', __FILE__, __LINE__ - 1
99
+ def to_s
100
+ "#{name} #{version}"
101
+ end
102
+ CODE
103
+ end
56
104
  end
57
105
 
106
+ # Runs the client API /sync method
107
+ # @param params [Hash] The sync options to use
108
+ # @option params [Numeric] :timeout (30.0) The timeout in seconds for the sync
109
+ # @option params :since The value of the batch token to base the sync from
110
+ # @option params [String,Hash] :filter The filter to use on the sync
111
+ # @option params [Boolean] :full_state Should the sync include the full state
112
+ # @option params [Boolean] :set_presence Should the sync set the user status to online
113
+ # @return [Response]
114
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#get-matrix-client-r0-sync
115
+ # For more information on the parameters and what they mean
58
116
  def sync(params = {})
59
117
  query = {
60
118
  timeout: 30.0
@@ -68,29 +126,76 @@ module MatrixSdk
68
126
  request(:get, :client_r0, '/sync', query: query)
69
127
  end
70
128
 
129
+ # Registers a user using the client API /register endpoint
130
+ #
131
+ # @example Regular user registration and login
132
+ # api.register(username: 'example', password: 'NotARealPass')
133
+ # # => { user_id: '@example:matrix.org', access_token: '...', home_server: 'matrix.org', device_id: 'ABCD123' }
134
+ # api.whoami?
135
+ # # => { user_id: '@example:matrix.org' }
136
+ #
137
+ # @param params [Hash] The registration information, all not handled by Ruby will be passed as JSON in the body
138
+ # @option params [String,Symbol] :kind ('user') The kind of registration to use
139
+ # @option params [Boolean] :store_token (true) Should the resulting access token be stored for the API
140
+ # @option params [Boolean] :store_device_id (store_token value) Should the resulting device ID be stored for the API
141
+ # @return [Response]
142
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-register
143
+ # For options that are permitted in this call
71
144
  def register(params = {})
72
145
  kind = params.delete(:kind) { 'user' }
146
+ store_token = params.delete(:store_token) { true }
147
+ store_device_id = params.delete(:store_device_id) { store_token }
73
148
 
74
- request(:post, :client_r0, '/register', body: params, query: { kind: kind })
149
+ request(:post, :client_r0, '/register', body: params, query: { kind: kind }).tap do |resp|
150
+ @access_token = resp.token if resp.key?(:token) && store_token
151
+ @device_id = resp.device_id if resp.key?(:device_id) && store_device_id
152
+ end
75
153
  end
76
154
 
155
+ # Logs in using the client API /login endpoint, and optionally stores the resulting access for API usage
156
+ #
157
+ # @example Logging in with username and password
158
+ # api.login(user: 'example', password: 'NotARealPass')
159
+ # # => { user_id: '@example:matrix.org', access_token: '...', home_server: 'matrix.org', device_id: 'ABCD123' }
160
+ # api.whoami?
161
+ # # => { user_id: '@example:matrix.org' }
162
+ #
163
+ # @example Advanced login, without storing details
164
+ # api.whoami?
165
+ # # => { user_id: '@example:matrix.org' }
166
+ # api.login(medium: 'email', address: 'someone@somewhere.net', password: '...', store_token: false)
167
+ # # => { user_id: '@someone:matrix.org', access_token: ...
168
+ # api.whoami?.user_id
169
+ # # => '@example:matrix.org'
170
+ #
171
+ # @param params [Hash] The login information to use, along with options for said log in
172
+ # @option params [Boolean] :store_token (true) Should the resulting access token be stored for the API
173
+ # @option params [Boolean] :store_device_id (store_token value) Should the resulting device ID be stored for the API
174
+ # @option params [String] :login_type ('m.login.password') The type of login to attempt
175
+ # @option params [String] :initial_device_display_name (USER_AGENT) The device display name to specify for this login attempt
176
+ # @option params [String] :device_id The device ID to set on the login
177
+ # @return [Response] A response hash with the parameters :user_id, :access_token, :home_server, and :device_id.
178
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-login
179
+ # The Matrix Spec, for more information about the call and response
77
180
  def login(params = {})
78
181
  options = {}
79
182
  options[:store_token] = params.delete(:store_token) { true }
80
- options[:store_device_id] = params.delete(:store_device_id) { true }
183
+ options[:store_device_id] = params.delete(:store_device_id) { options[:store_token] }
81
184
 
82
185
  data = {
83
186
  type: params.delete(:login_type) { 'm.login.password' },
84
- initial_device_display_name: params.delete(:initial_device_display_name) { user_agent }
187
+ initial_device_display_name: params.delete(:initial_device_display_name) { USER_AGENT }
85
188
  }.merge params
86
189
  data[:device_id] = device_id if device_id
87
190
 
88
191
  request(:post, :client_r0, '/login', body: data).tap do |resp|
89
- @access_token = resp[:token] if resp[:token] && options[:store_token]
90
- @device_id = resp[:device_id] if resp[:device_id] && options[:store_device_id]
192
+ @access_token = resp.token if resp.key?(:token) && options[:store_token]
193
+ @device_id = resp.device_id if resp.key?(:device_id) && options[:store_device_id]
91
194
  end
92
195
  end
93
196
 
197
+ # Logs out the currently logged in user
198
+ # @return [Response]
94
199
  def logout
95
200
  request(:post, :client_r0, '/logout')
96
201
  end
@@ -106,14 +211,20 @@ module MatrixSdk
106
211
  end
107
212
 
108
213
  def join_room(id_or_alias)
109
- request(:post, :client_r0, "/join/#{CGI.escape id_or_alias}")
214
+ id_or_alias = CGI.escape id_or_alias.to_s
215
+
216
+ request(:post, :client_r0, "/join/#{id_or_alias}")
110
217
  end
111
218
 
112
219
  def send_state_event(room_id, event_type, content, params = {})
113
220
  query = {}
114
221
  query[:ts] = params[:timestamp].to_i if params.key? :timestamp
115
222
 
116
- request(:put, :client_r0, "/rooms/#{room_id}/state/#{event_type}#{"/#{params[:state_key]}" if params.key? :state_key}", body: content, query: query)
223
+ room_id = CGI.escape room_id.to_s
224
+ event_type = CGI.escape event_type.to_s
225
+ state_key = CGI.escape params[:state_key].to_s if params.key? :state_key
226
+
227
+ request(:put, :client_r0, "/rooms/#{room_id}/state/#{event_type}#{"/#{state_key}" unless state_key.nil?}", body: content, query: query)
117
228
  end
118
229
 
119
230
  def send_message_event(room_id, event_type, content, params = {})
@@ -123,6 +234,10 @@ module MatrixSdk
123
234
  txn_id = transaction_id
124
235
  txn_id = params.fetch(:txn_id, "#{txn_id}#{Time.now.to_i}")
125
236
 
237
+ room_id = CGI.escape room_id.to_s
238
+ event_type = CGI.escape event_type.to_s
239
+ txn_id = CGI.escape txn_id.to_s
240
+
126
241
  request(:put, :client_r0, "/rooms/#{room_id}/send/#{event_type}/#{txn_id}", body: content, query: query)
127
242
  end
128
243
 
@@ -136,6 +251,10 @@ module MatrixSdk
136
251
  txn_id = transaction_id
137
252
  txn_id = params.fetch(:txn_id, "#{txn_id}#{Time.now.to_i}")
138
253
 
254
+ room_id = CGI.escape room_id.to_s
255
+ event_type = CGI.escape event_type.to_s
256
+ txn_id = CGI.escape txn_id.to_s
257
+
139
258
  request(:put, :client_r0, "/rooms/#{room_id}/redact/#{event_type}/#{txn_id}", body: content, query: query)
140
259
  end
141
260
 
@@ -195,11 +314,20 @@ module MatrixSdk
195
314
  }
196
315
  query[:to] = params[:to] if params.key? :to
197
316
 
317
+ room_id = CGI.escape room_id.to_s
318
+
198
319
  request(:get, :client_r0, "/rooms/#{room_id}/messages", query: query)
199
320
  end
200
321
 
322
+ def get_room_state(room_id, state_type)
323
+ room_id = CGI.escape room_id.to_s
324
+ state_type = CGI.escape state_type.to_s
325
+
326
+ request(:get, :client_r0, "/rooms/#{room_id}/state/#{state_type}")
327
+ end
328
+
201
329
  def get_room_name(room_id)
202
- request(:get, :client_r0, "/rooms/#{room_id}/state/m.room.name")
330
+ get_room_state(room_id, 'm.room.name')
203
331
  end
204
332
 
205
333
  def set_room_name(room_id, name, params = {})
@@ -210,7 +338,7 @@ module MatrixSdk
210
338
  end
211
339
 
212
340
  def get_room_topic(room_id)
213
- request(:get, :client_r0, "/rooms/#{room_id}/state/m.room.topic")
341
+ get_room_state(room_id, 'm.room.topic')
214
342
  end
215
343
 
216
344
  def set_room_topic(room_id, topic, params = {})
@@ -221,7 +349,7 @@ module MatrixSdk
221
349
  end
222
350
 
223
351
  def get_power_levels(room_id)
224
- request(:get, :client_r0, "/rooms/#{room_id}/state/m.room.power_levels")
352
+ get_room_state(room_id, 'm.room.power_levels')
225
353
  end
226
354
 
227
355
  def set_power_levels(room_id, content)
@@ -230,10 +358,14 @@ module MatrixSdk
230
358
  end
231
359
 
232
360
  def leave_room(room_id)
361
+ room_id = CGI.escape room_id.to_s
362
+
233
363
  request(:post, :client_r0, "/rooms/#{room_id}/leave")
234
364
  end
235
365
 
236
366
  def forget_room(room_id)
367
+ room_id = CGI.escape room_id.to_s
368
+
237
369
  request(:post, :client_r0, "/rooms/#{room_id}/forget")
238
370
  end
239
371
 
@@ -241,6 +373,9 @@ module MatrixSdk
241
373
  content = {
242
374
  user_id: user_id
243
375
  }
376
+
377
+ room_id = CGI.escape room_id.to_s
378
+
244
379
  request(:post, :client_r0, "/rooms/#{room_id}/invite", body: content)
245
380
  end
246
381
 
@@ -249,6 +384,9 @@ module MatrixSdk
249
384
  end
250
385
 
251
386
  def get_membership(room_id, user_id)
387
+ room_id = CGI.escape room_id.to_s
388
+ user_id = CGI.escape user_id.to_s
389
+
252
390
  request(:get, :client_r0, "/rooms/#{room_id}/state/m.room.member/#{user_id}")
253
391
  end
254
392
 
@@ -268,6 +406,9 @@ module MatrixSdk
268
406
  user_id: user_id,
269
407
  reason: params[:reason] || ''
270
408
  }
409
+
410
+ room_id = CGI.escape room_id.to_s
411
+
271
412
  request(:post, :client_r0, "/rooms/#{room_id}/ban", body: content)
272
413
  end
273
414
 
@@ -275,14 +416,24 @@ module MatrixSdk
275
416
  content = {
276
417
  user_id: user_id
277
418
  }
419
+
420
+ room_id = CGI.escape room_id.to_s
421
+
278
422
  request(:post, :client_r0, "/rooms/#{room_id}/unban", body: content)
279
423
  end
280
424
 
281
425
  def get_user_tags(user_id, room_id)
426
+ room_id = CGI.escape room_id.to_s
427
+ user_id = CGI.escape user_id.to_s
428
+
282
429
  request(:get, :client_r0, "/user/#{user_id}/rooms/#{room_id}/tags")
283
430
  end
284
431
 
285
432
  def remove_user_tag(user_id, room_id, tag)
433
+ room_id = CGI.escape room_id.to_s
434
+ user_id = CGI.escape user_id.to_s
435
+ tag = CGI.escape tag.to_s
436
+
286
437
  request(:delete, :client_r0, "/user/#{user_id}/rooms/#{room_id}/tags/#{tag}")
287
438
  end
288
439
 
@@ -293,34 +444,47 @@ module MatrixSdk
293
444
  content = {}
294
445
  content[:order] = params[:order] if params.key? :order
295
446
  end
447
+
448
+ room_id = CGI.escape room_id.to_s
449
+ user_id = CGI.escape user_id.to_s
450
+ tag = CGI.escape tag.to_s
451
+
296
452
  request(:put, :client_r0, "/user/#{user_id}/rooms/#{room_id}/tags/#{tag}", body: content)
297
453
  end
298
454
 
299
- def get_account_data(user_id, type)
300
- request(:get, :client_r0, "/user/#{user_id}/account_data/#{type}")
301
- end
455
+ # def get_account_data(user_id, type)
456
+ # request(:get, :client_r0, "/user/#{user_id}/account_data/#{type}")
457
+ # end
302
458
 
303
- def set_account_data(user_id, type, account_data)
304
- request(:put, :client_r0, "/user/#{user_id}/account_data/#{type}", body: account_data)
305
- end
459
+ def set_account_data(user_id, type_key, account_data)
460
+ user_id = CGI.escape user_id.to_s
461
+ type_key = CGI.escape type_key.to_s
306
462
 
307
- def get_room_account_data(user_id, room_id, type)
308
- request(:get, :client_r0, "/user/#{user_id}/rooms/#{room_id}/account_data/#{type}")
463
+ request(:put, :client_r0, "/user/#{user_id}/account_data/#{type_key}", body: account_data)
309
464
  end
310
465
 
311
- def set_room_account_data(user_id, room_id, type, account_data)
312
- request(:put, :client_r0, "/user/#{user_id}/rooms/#{room_id}/account_data/#{type}", body: account_data)
313
- end
466
+ # def get_room_account_data(user_id, room_id, type)
467
+ # request(:get, :client_r0, "/user/#{user_id}/rooms/#{room_id}/account_data/#{type}")
468
+ # end
469
+
470
+ def set_room_account_data(user_id, room_id, type_key, account_data)
471
+ user_id = CGI.escape user_id.to_s
472
+ room_id = CGI.escape room_id.to_s
473
+ type_key = CGI.escape type_key.to_s
314
474
 
315
- def get_room_state(room_id)
316
- request(:get, :client_r0, "/rooms/#{room_id}/state")
475
+ request(:put, :client_r0, "/user/#{user_id}/rooms/#{room_id}/account_data/#{type_key}", body: account_data)
317
476
  end
318
477
 
319
478
  def get_filter(user_id, filter_id)
479
+ user_id = CGI.escape user_id.to_s
480
+ filter_id = CGI.escape filter_id.to_s
481
+
320
482
  request(:get, :client_r0, "/user/#{user_id}/filter/#{filter_id}")
321
483
  end
322
484
 
323
485
  def create_filter(user_id, filter_params)
486
+ user_id = CGI.escape user_id.to_s
487
+
324
488
  request(:post, :client_r0, "/user/#{user_id}/filter", body: filter_params)
325
489
  end
326
490
 
@@ -329,17 +493,24 @@ module MatrixSdk
329
493
  end
330
494
 
331
495
  def get_display_name(user_id)
496
+ user_id = CGI.escape user_id.to_s
497
+
332
498
  request(:get, :client_r0, "/profile/#{user_id}/displayname")
333
499
  end
334
500
 
335
501
  def set_display_name(user_id, display_name)
336
502
  content = {
337
- display_name: display_name
503
+ displayname: display_name
338
504
  }
505
+
506
+ user_id = CGI.escape user_id.to_s
507
+
339
508
  request(:put, :client_r0, "/profile/#{user_id}/displayname", body: content)
340
509
  end
341
510
 
342
511
  def get_avatar_url(user_id)
512
+ user_id = CGI.escape user_id.to_s
513
+
343
514
  request(:get, :client_r0, "/profile/#{user_id}/avatar_url")
344
515
  end
345
516
 
@@ -347,6 +518,9 @@ module MatrixSdk
347
518
  content = {
348
519
  avatar_url: url
349
520
  }
521
+
522
+ user_id = CGI.escape user_id.to_s
523
+
350
524
  request(:put, :client_r0, "/profile/#{user_id}/avatar_url", body: content)
351
525
  end
352
526
 
@@ -355,11 +529,14 @@ module MatrixSdk
355
529
  raise 'Not a mxc:// URL' unless mxcurl.is_a? URI::MATRIX
356
530
 
357
531
  homeserver.dup.tap do |u|
358
- u.path = "/_matrix/media/r0/download/#{mxcurl.full_path}"
532
+ full_path = CGI.escape mxcurl.full_path.to_s
533
+ u.path = "/_matrix/media/r0/download/#{full_path}"
359
534
  end
360
535
  end
361
536
 
362
537
  def get_room_id(room_alias)
538
+ room_alias = CGI.escape room_alias.to_s
539
+
363
540
  request(:get, :client_r0, "/directory/room/#{room_alias}")
364
541
  end
365
542
 
@@ -367,14 +544,21 @@ module MatrixSdk
367
544
  content = {
368
545
  room_id: room_id
369
546
  }
547
+
548
+ room_alias = CGI.escape room_alias.to_s
549
+
370
550
  request(:put, :client_r0, "/directory/room/#{room_alias}", body: content)
371
551
  end
372
552
 
373
553
  def remove_room_alias(room_alias)
554
+ room_alias = CGI.escape room_alias.to_s
555
+
374
556
  request(:delete, :client_r0, "/directory/room/#{room_alias}")
375
557
  end
376
558
 
377
559
  def get_room_members(room_id)
560
+ room_id = CGI.escape room_id.to_s
561
+
378
562
  request(:get, :client_r0, "/rooms/#{room_id}/members")
379
563
  end
380
564
 
@@ -382,6 +566,7 @@ module MatrixSdk
382
566
  content = {
383
567
  join_rule: join_rule
384
568
  }
569
+
385
570
  send_state_event(room_id, 'm.room.join_rules', content)
386
571
  end
387
572
 
@@ -400,7 +585,7 @@ module MatrixSdk
400
585
  def request(method, api, path, options = {})
401
586
  url = homeserver.dup.tap do |u|
402
587
  u.path = api_to_path(api) + path
403
- u.query = [u.query, options[:query].map { |k, v| "#{k}#{"=#{v}" unless v.nil?}" }].flatten.reject(&:nil?).join('&') if options[:query]
588
+ u.query = [u.query, URI.encode_www_form(options.fetch(:query))].flatten.compact.join('&') if options[:query]
404
589
  u.query = nil if u.query.nil? || u.query.empty?
405
590
  end
406
591
  request = Net::HTTP.const_get(method.to_s.capitalize.to_sym).new url.request_uri
@@ -408,10 +593,13 @@ module MatrixSdk
408
593
  request.body = request.body.to_json if options.key?(:body) && !request.body.is_a?(String)
409
594
  request.body_stream = options[:body_stream] if options.key? :body_stream
410
595
 
411
- request.content_type = 'application/json' if request.body || request.body_stream
596
+ global_headers.each { |h, v| request[h] = v }
597
+ if request.body || request.body_stream
598
+ request.content_type = 'application/json'
599
+ request.content_length = (request.body || request.body_stream).size
600
+ end
412
601
 
413
602
  request['authorization'] = "Bearer #{access_token}" if access_token
414
- request['user-agent'] = user_agent
415
603
  if options.key? :headers
416
604
  options[:headers].each do |h, v|
417
605
  request[h.to_s.downcase] = v
@@ -428,13 +616,14 @@ module MatrixSdk
428
616
  data = JSON.parse(response.body, symbolize_names: true) rescue nil
429
617
 
430
618
  if response.is_a? Net::HTTPTooManyRequests
619
+ raise MatrixRequestError.new(data, response.code) unless autoretry
431
620
  failures += 1
432
621
  waittime = data[:retry_after_ms] || data[:error][:retry_after_ms] || @backoff_time
433
622
  sleep(waittime.to_f / 1000.0)
434
623
  next
435
624
  end
436
625
 
437
- return data if response.is_a? Net::HTTPSuccess
626
+ return MatrixSdk::Response.new self, data if response.is_a? Net::HTTPSuccess
438
627
  raise MatrixRequestError.new(data, response.code) if data
439
628
  raise MatrixConnectionError, response
440
629
  end
@@ -443,6 +632,8 @@ module MatrixSdk
443
632
  private
444
633
 
445
634
  def print_http(http)
635
+ return unless logger.debug?
636
+
446
637
  if http.is_a? Net::HTTPRequest
447
638
  dir = '>'
448
639
  logger.debug "#{dir} Sending a #{http.method} request to `#{http.path}`:"
@@ -450,11 +641,12 @@ module MatrixSdk
450
641
  dir = '<'
451
642
  logger.debug "#{dir} Received a #{http.code} #{http.message} response:"
452
643
  end
453
- http.to_hash.map { |k, v| "#{k}: #{k == 'authorization' ? '[redacted]' : v.join(', ')}" }.each do |h|
644
+ http.to_hash.map { |k, v| "#{k}: #{k == 'authorization' ? '[ REDACTED ]' : v.join(', ')}" }.each do |h|
454
645
  logger.debug "#{dir} #{h}"
455
646
  end
456
647
  logger.debug dir
457
- logger.debug "#{dir} #{http.body.length < 200 ? http.body : http.body.slice(0..200) + '... [truncated]'}" if http.body
648
+ clean_body = JSON.parse(http.body).each { |k, v| v.replace('[ REDACTED ]') if %w[password access_token].include? k }.to_json if http.body
649
+ logger.debug "#{dir} #{clean_body.length < 200 ? clean_body : clean_body.slice(0..200) + "... [truncated, #{clean_body.length} Bytes]"}" if clean_body
458
650
  end
459
651
 
460
652
  def transaction_id
@@ -472,13 +664,10 @@ module MatrixSdk
472
664
  @http ||= Net::HTTP.new homeserver.host, homeserver.port
473
665
  return @http if @http.active?
474
666
 
667
+ @http.read_timeout = read_timeout
475
668
  @http.use_ssl = homeserver.scheme == 'https'
476
669
  @http.verify_mode = validate_certificate ? ::OpenSSL::SSL::VERIFY_NONE : nil
477
670
  @http.start
478
671
  end
479
-
480
- def user_agent
481
- "Ruby Matrix SDK v#{MatrixSdk::VERSION}"
482
- end
483
672
  end
484
673
  end
@@ -7,13 +7,13 @@ module MatrixSdk
7
7
  extend Forwardable
8
8
 
9
9
  attr_reader :api
10
- attr_accessor :cache, :mxid, :sync_filter
10
+ attr_writer :mxid
11
+ attr_accessor :cache, :sync_filter
11
12
 
12
13
  events :event, :presence_event, :invite_event, :left_event, :ephemeral_event
13
14
  ignore_inspect :api,
14
15
  :on_event, :on_presence_event, :on_invite_event, :on_left_event, :on_ephemeral_event
15
16
 
16
- alias user_id mxid
17
17
  alias user_id= mxid=
18
18
 
19
19
  def_delegators :@api,
@@ -23,19 +23,27 @@ module MatrixSdk
23
23
  def initialize(hs_url, params = {})
24
24
  event_initialize
25
25
 
26
- params[:user_id] = params[:mxid] if params[:mxid]
27
- raise ArgumentError, 'Must provide user_id with access_token' if params[:access_token] && !params[:user_id]
26
+ params[:user_id] ||= params[:mxid] if params[:mxid]
28
27
 
29
- @api = Api.new hs_url, params
28
+ if hs_url.is_a? Api
29
+ @api = hs_url
30
+ params.each do |k, v|
31
+ api.instance_variable_set("@#{k}", v) if api.instance_variable_defined? "@#{k}"
32
+ end
33
+ else
34
+ @api = Api.new hs_url, params
35
+ end
30
36
 
31
37
  @rooms = {}
32
- @cache = :all
38
+ @users = {}
39
+ @cache = params.fetch(:client_cache, :all)
33
40
 
34
41
  @sync_token = nil
35
42
  @sync_thread = nil
36
43
  @sync_filter = { room: { timeline: { limit: params.fetch(:sync_filter_limit, 20) } } }
37
44
 
38
45
  @should_listen = false
46
+ @next_batch = nil
39
47
 
40
48
  @bad_sync_timeout_limit = 60 * 60
41
49
 
@@ -47,13 +55,20 @@ module MatrixSdk
47
55
 
48
56
  return unless params[:user_id]
49
57
  @mxid = params[:user_id]
50
- sync
51
58
  end
52
59
 
53
60
  def logger
54
- @logger ||= Logging.logger[self.class.name]
61
+ @logger ||= Logging.logger[self]
62
+ end
63
+
64
+ def mxid
65
+ @mxid ||= begin
66
+ api.whoami?[:user_id] if api && api.access_token
67
+ end
55
68
  end
56
69
 
70
+ alias user_id mxid
71
+
57
72
  def rooms
58
73
  @rooms.values
59
74
  end
@@ -72,7 +87,7 @@ module MatrixSdk
72
87
  data = api.login(user: username, password: password)
73
88
  post_authentication(data)
74
89
 
75
- sync(timeout: params.fetch(:sync_timeout, 15)) unless params[:no_sync]
90
+ sync(timeout: params.fetch(:sync_timeout, 15), full_state: params.fetch(:full_state, false)) unless params[:no_sync]
76
91
  end
77
92
 
78
93
  def logout
@@ -81,6 +96,10 @@ module MatrixSdk
81
96
  @mxid = nil
82
97
  end
83
98
 
99
+ def logged_in?
100
+ !(mxid.nil? || @api.access_token.nil?)
101
+ end
102
+
84
103
  def create_room(room_alias = nil, params = {})
85
104
  api.create_room(params.merge(room_alias: room_alias))
86
105
  end
@@ -95,7 +114,11 @@ module MatrixSdk
95
114
  end
96
115
 
97
116
  def get_user(user_id)
98
- User.new(self, user_id)
117
+ if cache == :all
118
+ @users[user_id] ||= User.new(self, user_id)
119
+ else
120
+ User.new(self, user_id)
121
+ end
99
122
  end
100
123
 
101
124
  def remove_room_alias(room_alias)
@@ -108,8 +131,8 @@ module MatrixSdk
108
131
  raise MatrixUnexpectedResponseError, 'Upload succeeded, but no media URI returned'
109
132
  end
110
133
 
111
- def listen_for_events(timeout = 30)
112
- sync(timeout: timeout)
134
+ def listen_for_events(timeout = 30, arguments = {})
135
+ sync(arguments.merge(timeout: timeout))
113
136
  end
114
137
 
115
138
  def start_listener_thread(params = {})
@@ -131,12 +154,14 @@ module MatrixSdk
131
154
  def listen_forever(params = {})
132
155
  timeout = params.fetch(:timeout, 30)
133
156
  params[:bad_sync_timeout] = params.fetch(:bad_sync_timeout, 5)
157
+ params[:sync_interval] = params.fetch(:sync_interval, 30)
134
158
 
135
159
  bad_sync_timeout = params[:bad_sync_timeout]
136
160
  while @should_listen
137
161
  begin
138
162
  sync(timeout: timeout)
139
163
  bad_sync_timeout = params[:bad_sync_timeout]
164
+ sleep(params[:sync_interval]) if params[:sync_interval] > 0
140
165
  rescue MatrixRequestError => ex
141
166
  logger.warn("A #{ex.class} occurred during sync")
142
167
  if ex.httpstatus >= 500
@@ -191,7 +216,12 @@ module MatrixSdk
191
216
  end
192
217
 
193
218
  def sync(params = {})
194
- data = api.sync params.merge(filter: sync_filter.to_json)
219
+ extra_params = {
220
+ filter: sync_filter.to_json
221
+ }
222
+ extra_params[:since] = @next_batch unless @next_batch.nil?
223
+ data = api.sync params.merge(extra_params)
224
+ @next_batch = data[:next_batch]
195
225
 
196
226
  data[:presence][:events].each do |presence_update|
197
227
  fire_presence_event(MatrixEvent.new(self, presence_update))
@@ -52,13 +52,23 @@ end
52
52
  def ignore_inspect(*symbols)
53
53
  class_eval %*
54
54
  def inspect
55
- "#<\#{self.class.name}:\#{"%016x" % (object_id << 1)} \#{instance_variables.reject { |f| %i[#{symbols.map { |s| "@#{s}" }.join ' '}].include? f }.map { |f| "\#{f}=\#{instance_variable_get(f).inspect}" }.join ' ' }>"
55
+ "\#{to_s[0..-2]} \#{instance_variables
56
+ .reject { |f| %i[#{symbols.map { |s| "@#{s}" }.join ' '}].include? f }
57
+ .map { |f| "\#{f}=\#{instance_variable_get(f).inspect}" }.join " " }}>"
56
58
  end
57
59
  *, __FILE__, __LINE__ - 4
58
60
  end
59
61
 
60
62
  module MatrixSdk
61
63
  class EventHandlerArray < Hash
64
+ attr_accessor :reraise_exceptions
65
+
66
+ def initialize(*args)
67
+ @reraise_exceptions = false
68
+
69
+ super(*args)
70
+ end
71
+
62
72
  def add_handler(filter = nil, id = nil, &block)
63
73
  id ||= block.hash
64
74
  self[id] = { filter: filter, id: id, block: block }
@@ -70,9 +80,19 @@ module MatrixSdk
70
80
 
71
81
  def fire(event, filter = nil)
72
82
  reverse_each do |_k, h|
73
- h[:block].call(event) unless event.matches?(h[:filter], filter)
83
+ begin
84
+ h[:block].call(event) if event.matches?(h[:filter], filter)
85
+ rescue StandardError => ex
86
+ logger.error "#{ex.class.name} occurred when firing event (#{event})\n#{ex}"
87
+
88
+ raise ex if @reraise_exceptions
89
+ end
74
90
  end
75
91
  end
92
+
93
+ def logger
94
+ @logger ||= Logging.logger[self]
95
+ end
76
96
  end
77
97
 
78
98
  class Event
@@ -115,5 +135,22 @@ module MatrixSdk
115
135
  to_match == filter
116
136
  end
117
137
  end
138
+
139
+ def [](key)
140
+ event[key]
141
+ end
142
+
143
+ def to_s
144
+ "#{event[:type]}: #{event.reject { |k, _v| k == :type }.to_json}"
145
+ end
146
+
147
+ def method_missing(method, *args)
148
+ return event[method] if event.key? method
149
+ super
150
+ end
151
+
152
+ def respond_to_missing?(method)
153
+ event.key? method
154
+ end
118
155
  end
119
156
  end
@@ -0,0 +1,41 @@
1
+ module MatrixSdk
2
+ # An usability wrapper for API responses as an extended [Hash]
3
+ # All results can be read as both hash keys and as read-only methods on the key
4
+ #
5
+ # @example Simple usage of the response wrapper to get the avatar URL
6
+ # resp = api.get_avatar_url(api.whoami?.user_id)
7
+ # # => { avatar_url: 'mxc://matrix.org/SDGdghriugerRg' }
8
+ # resp.is_a? Hash
9
+ # # => true
10
+ # resp.key? :avatar_url
11
+ # # => true
12
+ # resp.avatar_url
13
+ # # => 'mxc://matrix.org/SDGdghriugerRg'
14
+ # resp.api.set_avatar_url(...)
15
+ # # => {}
16
+ #
17
+ # @since 0.0.3
18
+ # @see Hash
19
+ # @!attribute [r] api
20
+ # @return [Api] The API connection that returned the response
21
+ module Response
22
+ def self.new(api, data)
23
+ data.extend(Extensions)
24
+ data.instance_variable_set(:@api, api)
25
+ data
26
+ end
27
+
28
+ module Extensions
29
+ attr_reader :api
30
+
31
+ def respond_to_missing?(name, *_args)
32
+ key? name
33
+ end
34
+
35
+ def method_missing(name, *args)
36
+ return fetch(name) if key?(name) && args.empty?
37
+ super
38
+ end
39
+ end
40
+ end
41
+ end
@@ -78,7 +78,7 @@ module MatrixSdk
78
78
  end
79
79
 
80
80
  def logger
81
- Logging.logger[self.class.name]
81
+ @logger ||= Logging.logger[self]
82
82
  end
83
83
 
84
84
  #
@@ -261,34 +261,54 @@ module MatrixSdk
261
261
  # User Management
262
262
  #
263
263
 
264
+ # Invites a user into the room
265
+ # @param user_id [String,User] the MXID of the user
266
+ # @return [Boolean] wether the action succeeded
264
267
  def invite_user(user_id)
268
+ user_id = user_id.id if user_id.is_a? MatrixSdk::User
265
269
  client.api.invite_user(id, user_id)
266
270
  true
267
271
  rescue MatrixError
268
272
  false
269
273
  end
270
274
 
275
+ # Kicks a user from the room
276
+ # @param user_id [String,User] the MXID of the user
277
+ # @param reason [String] the reason for the kick
278
+ # @return [Boolean] wether the action succeeded
271
279
  def kick_user(user_id, reason = '')
280
+ user_id = user_id.id if user_id.is_a? MatrixSdk::User
272
281
  client.api.kick_user(id, user_id, reason: reason)
273
282
  true
274
283
  rescue MatrixError
275
284
  false
276
285
  end
277
286
 
287
+ # Bans a user from the room
288
+ # @param user_id [String,User] the MXID of the user
289
+ # @param reason [String] the reason for the ban
290
+ # @return [Boolean] wether the action succeeded
278
291
  def ban_user(user_id, reason = '')
292
+ user_id = user_id.id if user_id.is_a? MatrixSdk::User
279
293
  client.api.ban_user(id, user_id, reason: reason)
280
294
  true
281
295
  rescue MatrixError
282
296
  false
283
297
  end
284
298
 
299
+ # Unbans a user from the room
300
+ # @param user_id [String,User] the MXID of the user
301
+ # @return [Boolean] wether the action succeeded
285
302
  def unban_user(user_id)
303
+ user_id = user_id.id if user_id.is_a? MatrixSdk::User
286
304
  client.api.unban_user(id, user_id)
287
305
  true
288
306
  rescue MatrixError
289
307
  false
290
308
  end
291
309
 
310
+ # Requests to be removed from the room
311
+ # @return [Boolean] wether the request succeeded
292
312
  def leave
293
313
  client.api.leave_room(id)
294
314
  client.rooms.delete id
@@ -297,14 +317,25 @@ module MatrixSdk
297
317
  false
298
318
  end
299
319
 
320
+ # Retrieves a custom entry from the room-specific account data
321
+ # @param type [String] the data type to retrieve
322
+ # @return [Hash] the data that was stored under the given type
300
323
  def get_account_data(type)
301
324
  client.api.get_room_account_data(client.mxid, id, type)
302
325
  end
303
326
 
327
+ # Stores a custom entry into the room-specific account data
328
+ # @param type [String] the data type to store
329
+ # @param account_data [Hash] the data to store
304
330
  def set_account_data(type, account_data)
305
331
  client.api.set_room_account_data(client.mxid, id, type, account_data)
306
332
  end
307
333
 
334
+ # Changes the room-specific user profile
335
+ # @param params [Hash] the user profile changes to apply
336
+ # @option params [String] :display_name the new display name to use in the room
337
+ # @option params [String,URI] :avatar_url the new avatar URL to use in the room
338
+ # @note the avatar URL should be a mxc:// URI
308
339
  def set_user_profile(params = {})
309
340
  return nil unless params[:display_name] || params[:avatar_url]
310
341
  data = client.api.get_membership(id, client.mxid)
@@ -339,6 +370,8 @@ module MatrixSdk
339
370
  nil
340
371
  end
341
372
 
373
+ # Reloads the name of the room
374
+ # @return [Boolean] if the name was changed or not
342
375
  def reload_name!
343
376
  data = client.api.get_room_name(id)
344
377
  changed = data[:name] != name
@@ -355,6 +388,8 @@ module MatrixSdk
355
388
  nil
356
389
  end
357
390
 
391
+ # Reloads the topic of the room
392
+ # @return [Boolean] if the topic was changed or not
358
393
  def reload_topic!
359
394
  data = client.api.get_room_topic(id)
360
395
  changed = data[:topic] != topic
@@ -395,7 +430,7 @@ module MatrixSdk
395
430
 
396
431
  def invite_only=(invite_only)
397
432
  self.join_rule = invite_only ? :invite : :public
398
- @join_rule == :invite # rubocop:disable Lint/Void
433
+ @join_rule == :invite
399
434
  end
400
435
 
401
436
  def join_rule=(join_rule)
@@ -407,7 +442,7 @@ module MatrixSdk
407
442
 
408
443
  def allow_guests=(allow_guests)
409
444
  self.guest_access = (allow_guests ? :can_join : :forbidden)
410
- @guest_access == :can_join # rubocop:disable Lint/Void
445
+ @guest_access == :can_join
411
446
  end
412
447
 
413
448
  def guest_access=(guest_access)
@@ -417,6 +452,10 @@ module MatrixSdk
417
452
  nil
418
453
  end
419
454
 
455
+ # Modifies the power levels of the room
456
+ # @param users [Hash] the user-specific power levels to set or remove
457
+ # @param users_default [Hash] the default user power levels to set
458
+ # @return [Boolean] if the change was successful
420
459
  def modify_user_power_levels(users = nil, users_default = nil)
421
460
  return false if users.nil? && users_default.nil?
422
461
  data = client.api.get_power_levels(id)
@@ -434,6 +473,10 @@ module MatrixSdk
434
473
  false
435
474
  end
436
475
 
476
+ # Modifies the required power levels for actions in the room
477
+ # @param events [Hash] the event-specific power levels to change
478
+ # @param params [Hash] other power-level params to change
479
+ # @return [Boolean] if the change was successful
437
480
  def modify_required_power_levels(events = nil, params = {})
438
481
  return false if events.nil? && (params.nil? || params.empty?)
439
482
  data = client.api.get_power_levels(id)
@@ -3,9 +3,17 @@ require 'matrix_sdk'
3
3
  module MatrixSdk
4
4
  # A class for tracking information about a user on Matrix
5
5
  class User
6
+ # @!attribute [r] id
7
+ # @return [String] the MXID of the user
8
+ # @!attribute [r] client
9
+ # @return [Client] the client for the user
6
10
  attr_reader :id, :client
7
11
  alias user_id :id
8
12
 
13
+ # @!method inspect
14
+ # An inspect method that skips a handful of instance variables to avoid
15
+ # flooding the terminal with debug data.
16
+ # @return [String] a regular inspect string without the data for some variables
9
17
  ignore_inspect :client
10
18
 
11
19
  def initialize(client, id, data = {})
@@ -20,10 +28,14 @@ module MatrixSdk
20
28
  end
21
29
  end
22
30
 
31
+ # @!attribute [r] display_name
32
+ # @return [String] the display name
23
33
  def display_name
24
34
  @display_name ||= client.api.get_display_name(id)[:displayname]
25
35
  end
26
36
 
37
+ # @!attribute [w] display_name
38
+ # @param name [String] the display name to set
27
39
  def display_name=(name)
28
40
  client.api.set_display_name(id, name)
29
41
  @display_name = name
@@ -31,14 +43,18 @@ module MatrixSdk
31
43
  nil
32
44
  end
33
45
 
46
+ # Gets a friendly name of the user
47
+ # @return [String] either the display name or MXID if unset
34
48
  def friendly_name
35
49
  display_name || id
36
50
  end
37
51
 
52
+ # @!attribute [r] avatar_url
38
53
  def avatar_url
39
54
  @avatar_url ||= client.api.get_avatar_url(id)[:avatar_url]
40
55
  end
41
56
 
57
+ # @!attribute [w] avatar_url
42
58
  def avatar_url=(url)
43
59
  client.api.set_avatar_url(id, url)
44
60
  @avatar_url = url
@@ -1,3 +1,3 @@
1
1
  module MatrixSdk
2
- VERSION = '0.0.2'.freeze
2
+ VERSION = '0.0.3'.freeze
3
3
  end
data/lib/matrix_sdk.rb CHANGED
@@ -6,6 +6,7 @@ autoload :Logging, 'logging'
6
6
  module MatrixSdk
7
7
  autoload :Api, 'matrix_sdk/api'
8
8
  autoload :Client, 'matrix_sdk/client'
9
+ autoload :Response, 'matrix_sdk/response'
9
10
  autoload :Room, 'matrix_sdk/room'
10
11
  autoload :User, 'matrix_sdk/user'
11
12
 
@@ -19,9 +20,9 @@ module MatrixSdk
19
20
  end
20
21
 
21
22
  def self.logger
22
- @logger ||= Logging.logger[name].tap do |logger|
23
+ @logger ||= Logging.logger[self].tap do |logger|
23
24
  logger.add_appenders Logging.appenders.stdout
24
- logger.level = :warn
25
+ logger.level = :info
25
26
  end
26
27
  end
27
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matrix_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Olofsson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-11 00:00:00.000000000 Z
11
+ date: 2018-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logging
@@ -74,8 +74,10 @@ extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
76
  - ".gitignore"
77
+ - ".gitlab-ci.yml"
77
78
  - ".rubocop.yml"
78
79
  - ".travis.yml"
80
+ - CHANGELOG.md
79
81
  - Gemfile
80
82
  - LICENSE.txt
81
83
  - README.md
@@ -86,6 +88,7 @@ files:
86
88
  - lib/matrix_sdk/client.rb
87
89
  - lib/matrix_sdk/errors.rb
88
90
  - lib/matrix_sdk/extensions.rb
91
+ - lib/matrix_sdk/response.rb
89
92
  - lib/matrix_sdk/room.rb
90
93
  - lib/matrix_sdk/user.rb
91
94
  - lib/matrix_sdk/version.rb