matrix_sdk 0.0.3 → 0.0.4

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: fc787a1c2e4bac79cf05357500571df2e7734464023a5182d08614b9e45e9aac
4
- data.tar.gz: 465ea39af281892dcb299014b8a5b4bc0c869f6914974f40cb6fd21301090129
3
+ metadata.gz: 39fdb05386da317f2810f25e668ae14bdd261c807bafc61056fa09dd1d6a8175
4
+ data.tar.gz: 88b32840ca73b6588f36e35edcccac15e721b071c69a60c6cfc383dceaf67e5f
5
5
  SHA512:
6
- metadata.gz: a18893ee520aedfacc011cf5888b310875ee6929fa94967a0eeee01e91d592a56b19b190e6400e5e9338ccf477f9ac4cb1c480866fb720c1eecee7f0fb005a6f
7
- data.tar.gz: ed1d6b9eaad9795147ffb8bf319c4fed25598147a2af2f97048eb0285684c32fc7809e36ad891917f3499105778eb11409d8577941258c9fb94cee84b4c41dbd
6
+ metadata.gz: b04d1f07b5d9dd97f3a80a2adffe9a4a29983efc4ee7d1c116c0036233e017d5d9ead02abc9a3048fc9b0ba51c1ee3353fd7ae999a7b5bfc8a41294cd9c1b47c
7
+ data.tar.gz: a27b7a3bf9b8c411e6026107d3d0a66cd0e86ac96f6bd6284ccc37ec35e3fd67a94a99b1ad2e67f948dd63003bd4f7495fc66baf3b0d1dc880ee300e1aa49b70
data/.gitlab-ci.yml CHANGED
@@ -7,27 +7,31 @@ cache:
7
7
  - vendor/ruby
8
8
 
9
9
  before_script:
10
- - gem install bundler --no-ri --no-rdoc
10
+ - gem install bundler -N
11
11
  - bundle install -j $(nproc) --path vendor
12
12
 
13
13
  rubocop:
14
14
  before_script: []
15
15
  script:
16
- - gem install rubocop --no-ri --no-rdoc
17
- - rubocop
16
+ - gem install rubocop -N
17
+ - rubocop lib
18
18
 
19
- # rspec:
20
- # script:
21
- # - rspec spec
19
+ test:
20
+ script:
21
+ - GENERATE_REPORTS=true CI_REPORTS=reports bundle exec rake test
22
+ artifacts:
23
+ reports:
24
+ junit: "reports/TEST-*.xml"
22
25
 
23
26
  pages:
24
27
  stage: deploy
25
28
  before_script: []
26
29
  script:
27
- - gem install yard
30
+ - gem install yard -N
28
31
  - yard doc -o public/
29
32
  artifacts:
30
33
  paths:
31
34
  - public/
32
35
  only:
33
36
  - master
37
+ when: always
data/.rubocop.yml CHANGED
@@ -4,6 +4,10 @@ AllCops:
4
4
  - '*.spec'
5
5
  - 'Rakefile'
6
6
 
7
+ # Broken in CI
8
+ Lint/Void:
9
+ Enabled: false
10
+
7
11
  # Don't enforce documentation
8
12
  Style/Documentation:
9
13
  Enabled: false
@@ -12,7 +16,7 @@ Metrics/ClassLength:
12
16
  Enabled: false
13
17
 
14
18
  Metrics/MethodLength:
15
- Max: 40
19
+ Max: 50
16
20
 
17
21
  Metrics/LineLength:
18
22
  Max: 190
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## v0.0.4 - 2019-02-20
2
+
3
+ - Adds a parameter to the client abstraction to allow retrying syncs on timeouts
4
+ - Adds support for token-based login in the client abstraction
5
+ - Adds rudimentary username and password validation in the client abstraction
6
+ - Adds MXID validation in the client abstraction
7
+ - Adds a method to discover a homeserver address based on a domain.
8
+ - Supporting both SRV and .well-known lookups
9
+ - Adds methods from the r0.4.0 spec
10
+ - Adds support for version 3 event IDs
11
+ - Extends the connection exceptions with a specific timeout error
12
+ - Sets a series of filters in the simple client example to skip unhandled event
13
+ - Fixes an exception when null values end up in the body cleaner during debugging
14
+ - Fixes an error with CGI not being required correctly
15
+
1
16
  ## v0.0.3 - 2018-08-14
2
17
 
3
18
  - Adds missing accessors for HTTP timeout
data/Rakefile CHANGED
@@ -7,4 +7,9 @@ Rake::TestTask.new(:test) do |t|
7
7
  t.test_files = FileList['test/**/*_test.rb']
8
8
  end
9
9
 
10
+ if ENV['GENERATE_REPORTS'] == 'true'
11
+ require 'ci/reporter/rake/test_unit'
12
+ task :test => 'ci:setup:testunit'
13
+ end
14
+
10
15
  task :default => :test
@@ -3,19 +3,61 @@
3
3
  require 'io/console'
4
4
  require 'matrix_sdk'
5
5
 
6
+ # A filter to only discover joined rooms
7
+ ROOM_DISCOVERY_FILTER = {
8
+ event_fields: %w[sender membership],
9
+ presence: { senders: [], types: [] },
10
+ account_data: { senders: [], types: [] },
11
+ room: {
12
+ ephemeral: { senders: [], types: [] },
13
+ state: {
14
+ senders: [],
15
+ types: [
16
+ 'm.room.aliases',
17
+ 'm.room.canonical_alias',
18
+ 'm.room.member'
19
+ ]
20
+ },
21
+ timeline: { senders: [], types: [] },
22
+ account_data: { senders: [], types: [] }
23
+ }
24
+ }.freeze
25
+
26
+ # A filter to only retrieve messages from rooms
27
+ ROOM_STATE_FILTER = {
28
+ presence: { senders: [], types: [] },
29
+ account_data: { senders: [], types: [] },
30
+ room: {
31
+ ephemeral: { senders: [], types: [] },
32
+ state: {
33
+ types: ['m.room.member']
34
+ },
35
+ timeline: {
36
+ types: ['m.room.message']
37
+ },
38
+ account_data: { senders: [], types: [] }
39
+ }
40
+ }.freeze
41
+
42
+
6
43
  class SimpleClient < MatrixSdk::Client
7
44
  def initialize(hs_url)
8
45
  super hs_url, sync_filter_limit: 10
9
46
 
10
47
  @pls = {}
48
+ @tracked_rooms = []
49
+ @filter = ROOM_STATE_FILTER.dup
11
50
  end
12
51
 
13
52
  def add_listener(room)
14
53
  room.on_event.add_handler { |ev| on_message(room, ev) }
54
+ @tracked_rooms << room.id
15
55
  end
16
56
 
17
57
  def run
18
- start_listener_thread
58
+ # Only track messages from the listened rooms
59
+ @filter[:room][:rooms] = @tracked_rooms
60
+ start_listener_thread(filter: @filter.to_json)
19
61
  end
20
62
 
21
63
  private
@@ -64,7 +106,12 @@ if $PROGRAM_NAME == __FILE__
64
106
  password = STDIN.noecho(&:gets).strip
65
107
 
66
108
  puts 'Logging in...'
67
- client.login(user, password, sync_timeout: 5)
109
+ client.login(user, password, no_sync: true)
110
+
111
+ # Only retrieve list of joined room in first sync
112
+ sync_filter = client.sync_filter.merge(ROOM_DISCOVERY_FILTER)
113
+ sync_filter[:room][:state][:senders] << client.mxid
114
+ client.listen_for_events(5, filter: sync_filter.to_json)
68
115
 
69
116
  puts 'Finding room...'
70
117
  room = client.find_room(ARGV.last)
@@ -1,5 +1,6 @@
1
1
  require 'matrix_sdk'
2
2
 
3
+ require 'cgi'
3
4
  require 'json'
4
5
  require 'net/http'
5
6
  require 'openssl'
@@ -9,17 +10,19 @@ module MatrixSdk
9
10
  class Api
10
11
  USER_AGENT = "Ruby Matrix SDK v#{MatrixSdk::VERSION}".freeze
11
12
  DEFAULT_HEADERS = {
12
- 'accept' => 'application/json',
13
+ 'accept' => 'application/json',
13
14
  'user-agent' => USER_AGENT
14
15
  }.freeze
15
16
 
16
- attr_accessor :access_token, :device_id, :autoretry, :global_headers
17
+ attr_accessor :access_token, :connection_address, :connection_port, :device_id, :autoretry, :global_headers
17
18
  attr_reader :homeserver, :validate_certificate, :read_timeout
18
19
 
19
20
  ignore_inspect :access_token, :logger
20
21
 
21
22
  # @param homeserver [String,URI] The URL to the Matrix homeserver, without the /_matrix/ part
22
23
  # @param params [Hash] Additional parameters on creation
24
+ # @option params [String] :address The connection address to the homeserver, if different to the HS URL
25
+ # @option params [Integer] :port The connection port to the homeserver, if different to the HS URL
23
26
  # @option params [String] :access_token The access token to use for the connection
24
27
  # @option params [String] :device_id The ID of the logged in decide to use
25
28
  # @option params [Boolean] :autoretry (true) Should requests automatically be retried in case of rate limits
@@ -32,15 +35,11 @@ module MatrixSdk
32
35
  def initialize(homeserver, params = {})
33
36
  @homeserver = homeserver
34
37
  @homeserver = URI.parse("#{'https://' unless @homeserver.start_with? 'http'}#{@homeserver}") unless @homeserver.is_a? URI
35
- if @homeserver.path.end_with? '_matrix/'
36
- @homeserver.path = begin
37
- split = @homeserver.path.rpartition '_matrix/'
38
- (split[(split.find_index '_matrix/')] = '/') rescue nil
39
- split.join
40
- end
41
- end
38
+ @homeserver.path.gsub!(/\/?_matrix\/?/, '') if @homeserver.path =~ /_matrix\/?$/
42
39
  raise 'Please use the base URL for your HS (without /_matrix/)' if @homeserver.path.include? '/_matrix/'
43
40
 
41
+ @connection_address = params.fetch(:address, nil)
42
+ @connection_port = params.fetch(:port, nil)
44
43
  @access_token = params.fetch(:access_token, nil)
45
44
  @device_id = params.fetch(:device_id, nil)
46
45
  @autoretry = params.fetch(:autoretry, true)
@@ -55,6 +54,60 @@ module MatrixSdk
55
54
  @homeserver.userinfo = '' unless params[:skip_login]
56
55
  end
57
56
 
57
+ # Create an API connection to a domain entry
58
+ #
59
+ # This will follow the server discovery spec for client-server and federation
60
+ #
61
+ # @example Opening a Matrix API connection to a homeserver
62
+ # hs = MatrixSdk::API.new_for_domain 'example.com'
63
+ # hs.connection_address
64
+ # # => 'matrix.example.com'
65
+ # hs.connection_port
66
+ # # => 443
67
+ #
68
+ # @param domain [String] The domain to set up the API connection for, can contain a ':' to denote a port
69
+ # @param params [Hash] Additional options to pass to .new
70
+ # @return [API] The API connection
71
+ def self.new_for_domain(domain, params = {})
72
+ # Attempt SRV record discovery
73
+ srv = if domain.include? ':'
74
+ addr, port = domain.split ':'
75
+ Resolv::DNS::Resource::IN::SRV.new 10, 1, port.to_i, addr
76
+ else
77
+ require 'resolv'
78
+ resolver = Resolv::DNS.new
79
+ begin
80
+ resolver.getresource("_matrix._tcp.#{domain}")
81
+ rescue Resolv::ResolvError
82
+ nil
83
+ end
84
+ end
85
+
86
+ # Attempt .well-known discovery
87
+ if srv.nil?
88
+ well_known = begin
89
+ data = Net::HTTP.get("https://#{domain}/.well-known/matrix/client")
90
+ JSON.parse(data)
91
+ rescue StandardError
92
+ nil
93
+ end
94
+
95
+ return new(well_known['m.homeserver']['base_url']) if well_known &&
96
+ well_known.key?('m.homeserver') &&
97
+ well_known['m.homerserver'].key?('base_url')
98
+ end
99
+
100
+ # Fall back to A record on domain
101
+ srv ||= Resolv::DNS::Resource::IN::SRV.new 10, 1, 8448, domain
102
+
103
+ domain = domain.split(':').first if domain.include? ':'
104
+ new("https://#{domain}",
105
+ params.merge(
106
+ address: srv.target.to_s,
107
+ port: srv.port
108
+ ))
109
+ end
110
+
58
111
  # Gets the logger for the API
59
112
  # @return [Logging::Logger] The API-scope logger
60
113
  def logger
@@ -81,6 +134,7 @@ module MatrixSdk
81
134
  def homeserver=(hs_info)
82
135
  # TODO: DNS query for SRV information about HS?
83
136
  return unless hs_info.is_a? URI
137
+
84
138
  @http.finish if @http
85
139
  @homeserver = hs_info
86
140
  end
@@ -88,14 +142,32 @@ module MatrixSdk
88
142
  # Gets the available client API versions
89
143
  # @return [Array]
90
144
  def client_api_versions
91
- @client_api_versions ||= request(:get, :client, '/versions').versions
145
+ @client_api_versions ||= request(:get, :client, '/versions').versions.tap do |vers|
146
+ vers.instance_eval <<-'CODE', __FILE__, __LINE__ + 1
147
+ def latest
148
+ latest
149
+ end
150
+ CODE
151
+ end
152
+ end
153
+
154
+ # Gets the list of available unstable client API features
155
+ # @return [Array]
156
+ def client_api_unstable_features
157
+ @client_api_unstable_features ||= request(:get, :client, '/versions').unstable_features.tap do |vers|
158
+ vers.instance_eval <<-'CODE', __FILE__, __LINE__ + 1
159
+ def has?(feature)
160
+ fetch(feature, nil)
161
+ end
162
+ CODE
163
+ end
92
164
  end
93
165
 
94
166
  # Gets the server version
95
167
  # @note This uses the unstable federation/v1 API
96
168
  def server_version
97
169
  Response.new(self, request(:get, :federation_v1, '/version').server).tap do |resp|
98
- resp.instance_eval <<-'CODE', __FILE__, __LINE__ - 1
170
+ resp.instance_eval <<-'CODE', __FILE__, __LINE__ + 1
99
171
  def to_s
100
172
  "#{name} #{version}"
101
173
  end
@@ -195,11 +267,21 @@ module MatrixSdk
195
267
  end
196
268
 
197
269
  # Logs out the currently logged in user
198
- # @return [Response]
270
+ # @return [Response] An empty response if the logout was successful
271
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-logout
272
+ # The Matrix Spec, for more information about the call and response
199
273
  def logout
200
274
  request(:post, :client_r0, '/logout')
201
275
  end
202
276
 
277
+ # Creates a new room
278
+ # @param params [Hash] The room creation details
279
+ # @option params [Symbol] :visibility (:public) The room visibility
280
+ # @option params [String] :room_alias A room alias to apply on creation
281
+ # @option params [Boolean] :invite Should the room be created invite-only
282
+ # @return [Response] A response hash with ...
283
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-createroom
284
+ # The Matrix Spec, for more information about the call and response
203
285
  def create_room(params = {})
204
286
  content = {
205
287
  visibility: params.fetch(:visibility, :public)
@@ -210,12 +292,31 @@ module MatrixSdk
210
292
  request(:post, :client_r0, '/createRoom', content)
211
293
  end
212
294
 
295
+ # Joins a room
296
+ # @param id_or_alias [MXID,String] The room ID or Alias to join
297
+ # @return [Response] A response hash with the parameter :room_id
298
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-join-roomidoralias
299
+ # The Matrix Spec, for more information about the call and response
213
300
  def join_room(id_or_alias)
301
+ # id_or_alias = MXID.new id_or_alias.to_s unless id_or_alias.is_a? MXID
302
+ # raise ArgumentError, 'Not a room ID or alias' unless id_or_alias.room?
303
+
214
304
  id_or_alias = CGI.escape id_or_alias.to_s
215
305
 
216
306
  request(:post, :client_r0, "/join/#{id_or_alias}")
217
307
  end
218
308
 
309
+ # Sends a state event to a room
310
+ # @param room_id [MXID,String] The room ID to send the state event to
311
+ # @param event_type [String] The event type to send
312
+ # @param content [Hash] The contents of the state event
313
+ # @param params [Hash] Options for the request
314
+ # @option params [Integer] :timestamp The timestamp when the event was created, only used for AS events
315
+ # @option params [String] :state_key The state key of the event, if there is one
316
+ # @return [Response] A response hash with the parameter :event_id
317
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype-statekey
318
+ # https://matrix.org/docs/spec/client_server/r0.3.0.html#put-matrix-client-r0-rooms-roomid-state-eventtype
319
+ # The Matrix Spec, for more information about the call and response
219
320
  def send_state_event(room_id, event_type, content, params = {})
220
321
  query = {}
221
322
  query[:ts] = params[:timestamp].to_i if params.key? :timestamp
@@ -227,6 +328,16 @@ module MatrixSdk
227
328
  request(:put, :client_r0, "/rooms/#{room_id}/state/#{event_type}#{"/#{state_key}" unless state_key.nil?}", body: content, query: query)
228
329
  end
229
330
 
331
+ # Sends a message event to a room
332
+ # @param room_id [MXID,String] The room ID to send the message event to
333
+ # @param event_type [String] The event type of the message
334
+ # @param content [Hash] The contents of the message
335
+ # @param params [Hash] Options for the request
336
+ # @option params [Integer] :timestamp The timestamp when the event was created, only used for AS events
337
+ # @option params [Integer] :txn_id The ID of the transaction, or automatically generated
338
+ # @return [Response] A response hash with the parameter :event_id
339
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
340
+ # The Matrix Spec, for more information about the call and response
230
341
  def send_message_event(room_id, event_type, content, params = {})
231
342
  query = {}
232
343
  query[:ts] = params[:timestamp].to_i if params.key? :timestamp
@@ -241,7 +352,17 @@ module MatrixSdk
241
352
  request(:put, :client_r0, "/rooms/#{room_id}/send/#{event_type}/#{txn_id}", body: content, query: query)
242
353
  end
243
354
 
244
- def redact_event(room_id, event_type, params = {})
355
+ # Redact an event in a room
356
+ # @param room_id [MXID,String] The room ID to send the message event to
357
+ # @param event_id [String] The event ID of the event to redact
358
+ # @param params [Hash] Options for the request
359
+ # @option params [Integer] :timestamp The timestamp when the event was created, only used for AS events
360
+ # @option params [String] :reason The reason for the redaction
361
+ # @option params [Integer] :txn_id The ID of the transaction, or automatically generated
362
+ # @return [Response] A response hash with the parameter :event_id
363
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid
364
+ # The Matrix Spec, for more information about the call and response
365
+ def redact_event(room_id, event_id, params = {})
245
366
  query = {}
246
367
  query[:ts] = params[:timestamp].to_i if params.key? :timestamp
247
368
 
@@ -252,12 +373,53 @@ module MatrixSdk
252
373
  txn_id = params.fetch(:txn_id, "#{txn_id}#{Time.now.to_i}")
253
374
 
254
375
  room_id = CGI.escape room_id.to_s
255
- event_type = CGI.escape event_type.to_s
376
+ event_id = CGI.escape event_id.to_s
256
377
  txn_id = CGI.escape txn_id.to_s
257
378
 
258
- request(:put, :client_r0, "/rooms/#{room_id}/redact/#{event_type}/#{txn_id}", body: content, query: query)
379
+ request(:put, :client_r0, "/rooms/#{room_id}/redact/#{event_id}/#{txn_id}", body: content, query: query)
259
380
  end
260
381
 
382
+ # Send a content message to a room
383
+ #
384
+ # @example Sending an image to a room
385
+ # send_content('!abcd123:localhost',
386
+ # 'mxc://localhost/1234567',
387
+ # 'An image of a cat',
388
+ # 'm.image',
389
+ # extra_information: {
390
+ # h: 128,
391
+ # w: 128,
392
+ # mimetype: 'image/png',
393
+ # size: 1024
394
+ # })
395
+ #
396
+ # @example Sending a file to a room
397
+ # send_content('!example:localhost',
398
+ # 'mxc://localhost/fileurl',
399
+ # 'Contract.pdf',
400
+ # 'm.file',
401
+ # extra_content: {
402
+ # filename: 'contract.pdf'
403
+ # },
404
+ # extra_information: {
405
+ # mimetype: 'application/pdf',
406
+ # size: 96674
407
+ # })
408
+ #
409
+ # @param room_id [MXID,String] The room ID to send the content to
410
+ # @param url [URI,String] The URL to the content
411
+ # @param name [String] The name of the content
412
+ # @param msg_type [String] The message type of the content
413
+ # @param params [Hash] Options for the request
414
+ # @option params [Hash] :extra_information ({}) Extra information for the content
415
+ # @option params [Hash] :extra_content Extra data to insert into the content hash
416
+ # @return [Response] A response hash with the parameter :event_id
417
+ # @see send_message_event For more information on the underlying call
418
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#m-image
419
+ # https://matrix.org/docs/spec/client_server/r0.3.0.html#m-file
420
+ # https://matrix.org/docs/spec/client_server/r0.3.0.html#m-video
421
+ # https://matrix.org/docs/spec/client_server/r0.3.0.html#m-audio
422
+ # The Matrix Spec, for more information about the call and response
261
423
  def send_content(room_id, url, name, msg_type, params = {})
262
424
  content = {
263
425
  url: url,
@@ -265,22 +427,47 @@ module MatrixSdk
265
427
  body: name,
266
428
  info: params.delete(:extra_information) { {} }
267
429
  }
430
+ content.merge!(params.fetch(:extra_content)) if params.key? :extra_content
268
431
 
269
432
  send_message_event(room_id, 'm.room.message', content, params)
270
433
  end
271
434
 
435
+ # Send a geographic location to a room
436
+ #
437
+ # @param room_id [MXID,String] The room ID to send the location to
438
+ # @param geo_uri [URI,String] The geographical URI to send
439
+ # @param name [String] The name of the location
440
+ # @param params [Hash] Options for the request
441
+ # @option params [Hash] :extra_information ({}) Extra information for the location
442
+ # @option params [URI,String] :thumbnail_url The URL to a thumbnail of the location
443
+ # @option params [Hash] :thumbnail_info Image information about the location thumbnail
444
+ # @return [Response] A response hash with the parameter :event_id
445
+ # @see send_message_event For more information on the underlying call
446
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#m-location
447
+ # The Matrix Spec, for more information about the call and response
272
448
  def send_location(room_id, geo_uri, name, params = {})
273
449
  content = {
274
450
  geo_uri: geo_uri,
275
451
  msgtype: 'm.location',
276
- body: name
452
+ body: name,
453
+ info: params.delete(:extra_information) { {} }
277
454
  }
278
- content[:thumbnail_url] = params.delete(:thumbnail_url) if params.key? :thumbnail_url
279
- content[:thumbnail_info] = params.delete(:thumbnail_info) if params.key? :thumbnail_info
455
+ content[:info][:thumbnail_url] = params.delete(:thumbnail_url) if params.key? :thumbnail_url
456
+ content[:info][:thumbnail_info] = params.delete(:thumbnail_info) if params.key? :thumbnail_info
280
457
 
281
458
  send_message_event(room_id, 'm.room.message', content, params)
282
459
  end
283
460
 
461
+ # Send a plaintext message to a room
462
+ #
463
+ # @param room_id [MXID,String] The room ID to send the message to
464
+ # @param message [String] The message to send
465
+ # @param params [Hash] Options for the request
466
+ # @option params [String] :msg_type ('m.text') The message type to send
467
+ # @return [Response] A response hash with the parameter :event_id
468
+ # @see send_message_event For more information on the underlying call
469
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#m-text
470
+ # The Matrix Spec, for more information about the call and response
284
471
  def send_message(room_id, message, params = {})
285
472
  content = {
286
473
  msgtype: params.delete(:msg_type) { 'm.text' },
@@ -289,6 +476,16 @@ module MatrixSdk
289
476
  send_message_event(room_id, 'm.room.message', content, params)
290
477
  end
291
478
 
479
+ # Send a plaintext emote to a room
480
+ #
481
+ # @param room_id [MXID,String] The room ID to send the message to
482
+ # @param emote [String] The emote to send
483
+ # @param params [Hash] Options for the request
484
+ # @option params [String] :msg_type ('m.emote') The message type to send
485
+ # @return [Response] A response hash with the parameter :event_id
486
+ # @see send_message_event For more information on the underlying call
487
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#m-emote
488
+ # The Matrix Spec, for more information about the call and response
292
489
  def send_emote(room_id, emote, params = {})
293
490
  content = {
294
491
  msgtype: params.delete(:msg_type) { 'm.emote' },
@@ -297,6 +494,16 @@ module MatrixSdk
297
494
  send_message_event(room_id, 'm.room.message', content, params)
298
495
  end
299
496
 
497
+ # Send a plaintext notice to a room
498
+ #
499
+ # @param room_id [MXID,String] The room ID to send the message to
500
+ # @param notice [String] The notice to send
501
+ # @param params [Hash] Options for the request
502
+ # @option params [String] :msg_type ('m.notice') The message type to send
503
+ # @return [Response] A response hash with the parameter :event_id
504
+ # @see send_message_event For more information on the underlying call
505
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#m-notice
506
+ # The Matrix Spec, for more information about the call and response
300
507
  def send_notice(room_id, notice, params = {})
301
508
  content = {
302
509
  msgtype: params.delete(:msg_type) { 'm.notice' },
@@ -305,6 +512,18 @@ module MatrixSdk
305
512
  send_message_event(room_id, 'm.room.message', content, params)
306
513
  end
307
514
 
515
+ # Retrieve additional messages in a room
516
+ #
517
+ # @param room_id [MXID,String] The room ID to retrieve messages for
518
+ # @param token [String] The token to start retrieving from, can be from a sync or from an earlier get_room_messages call
519
+ # @param direction [:b,:f] The direction to retrieve messages
520
+ # @param params [Hash] Additional options for the request
521
+ # @option params [Integer] :limit (10) The limit of messages to retrieve
522
+ # @option params [String] :to A token to limit retrieval to
523
+ # @option params [String] :filter A filter to limit the retrieval to
524
+ # @return [Response] A response hash with the message information containing :start, :end, and :chunk fields
525
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#get-matrix-client-r0-rooms-roomid-messages
526
+ # The Matrix Spec, for more information about the call and response
308
527
  def get_room_messages(room_id, token, direction, params = {})
309
528
  query = {
310
529
  roomId: room_id,
@@ -313,12 +532,20 @@ module MatrixSdk
313
532
  limit: params.fetch(:limit, 10)
314
533
  }
315
534
  query[:to] = params[:to] if params.key? :to
535
+ query[:filter] = params.fetch(:filter) if params.key? :filter
316
536
 
317
537
  room_id = CGI.escape room_id.to_s
318
538
 
319
539
  request(:get, :client_r0, "/rooms/#{room_id}/messages", query: query)
320
540
  end
321
541
 
542
+ # Reads the latest instance of a room state event
543
+ #
544
+ # @param room_id [MXID,String] The room ID to read from
545
+ # @param state_type [String] The state type to read
546
+ # @return [Response] A response hash with the contents of the state event
547
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#get-matrix-client-r0-rooms-roomid-state-eventtype
548
+ # The Matrix Spec, for more information about the call and response
322
549
  def get_room_state(room_id, state_type)
323
550
  room_id = CGI.escape room_id.to_s
324
551
  state_type = CGI.escape state_type.to_s
@@ -326,6 +553,13 @@ module MatrixSdk
326
553
  request(:get, :client_r0, "/rooms/#{room_id}/state/#{state_type}")
327
554
  end
328
555
 
556
+ # Gets the display name of a room
557
+ #
558
+ # @param room_id [MXID,String] The room ID to look up
559
+ # @return [Response] A response hash with the parameter :name
560
+ # @see get_room_state
561
+ # @see https://matrix.org/docs/spec/client_server/r0.3.0.html#m-room-name
562
+ # The Matrix Spec, for more information about the event and data
329
563
  def get_room_name(room_id)
330
564
  get_room_state(room_id, 'm.room.name')
331
565
  end
@@ -452,9 +686,12 @@ module MatrixSdk
452
686
  request(:put, :client_r0, "/user/#{user_id}/rooms/#{room_id}/tags/#{tag}", body: content)
453
687
  end
454
688
 
455
- # def get_account_data(user_id, type)
456
- # request(:get, :client_r0, "/user/#{user_id}/account_data/#{type}")
457
- # end
689
+ def get_account_data(user_id, type_key)
690
+ user_id = CGI.escape user_id.to_s
691
+ type_key = CGI.escape type_key.to_s
692
+
693
+ request(:get, :client_r0, "/user/#{user_id}/account_data/#{type_key}")
694
+ end
458
695
 
459
696
  def set_account_data(user_id, type_key, account_data)
460
697
  user_id = CGI.escape user_id.to_s
@@ -463,9 +700,13 @@ module MatrixSdk
463
700
  request(:put, :client_r0, "/user/#{user_id}/account_data/#{type_key}", body: account_data)
464
701
  end
465
702
 
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
703
+ def get_room_account_data(user_id, room_id, type_key)
704
+ user_id = CGI.escape user_id.to_s
705
+ room_id = CGI.escape room_id.to_s
706
+ type_key = CGI.escape type_key.to_s
707
+
708
+ request(:get, :client_r0, "/user/#{user_id}/rooms/#{room_id}/account_data/#{type_key}")
709
+ end
469
710
 
470
711
  def set_room_account_data(user_id, room_id, type_key, account_data)
471
712
  user_id = CGI.escape user_id.to_s
@@ -617,6 +858,7 @@ module MatrixSdk
617
858
 
618
859
  if response.is_a? Net::HTTPTooManyRequests
619
860
  raise MatrixRequestError.new(data, response.code) unless autoretry
861
+
620
862
  failures += 1
621
863
  waittime = data[:retry_after_ms] || data[:error][:retry_after_ms] || @backoff_time
622
864
  sleep(waittime.to_f / 1000.0)
@@ -625,7 +867,8 @@ module MatrixSdk
625
867
 
626
868
  return MatrixSdk::Response.new self, data if response.is_a? Net::HTTPSuccess
627
869
  raise MatrixRequestError.new(data, response.code) if data
628
- raise MatrixConnectionError, response
870
+
871
+ raise MatrixConnectionError.class_by_code(response.code), response
629
872
  end
630
873
  end
631
874
 
@@ -645,8 +888,11 @@ module MatrixSdk
645
888
  logger.debug "#{dir} #{h}"
646
889
  end
647
890
  logger.debug dir
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
891
+ clean_body = JSON.parse(http.body) rescue nil if http.body
892
+ clean_body.keys.each { |k| clean_body[k] = '[ REDACTED ]' if %w[password access_token].include?(k) }.to_json if clean_body
649
893
  logger.debug "#{dir} #{clean_body.length < 200 ? clean_body : clean_body.slice(0..200) + "... [truncated, #{clean_body.length} Bytes]"}" if clean_body
894
+ rescue StandardError => ex
895
+ logger.warn "#{ex.class} occured while printing request debug; #{ex.message}\n#{ex.backtrace.join "\n"}"
650
896
  end
651
897
 
652
898
  def transaction_id
@@ -661,7 +907,7 @@ module MatrixSdk
661
907
  end
662
908
 
663
909
  def http
664
- @http ||= Net::HTTP.new homeserver.host, homeserver.port
910
+ @http ||= Net::HTTP.new (@connection_address || homeserver.host), (@connection_port || homeserver.port)
665
911
  return @http if @http.active?
666
912
 
667
913
  @http.read_timeout = read_timeout
@@ -7,20 +7,23 @@ module MatrixSdk
7
7
  extend Forwardable
8
8
 
9
9
  attr_reader :api
10
- attr_writer :mxid
11
10
  attr_accessor :cache, :sync_filter
12
11
 
13
12
  events :event, :presence_event, :invite_event, :left_event, :ephemeral_event
14
13
  ignore_inspect :api,
15
14
  :on_event, :on_presence_event, :on_invite_event, :on_left_event, :on_ephemeral_event
16
15
 
17
- alias user_id= mxid=
18
-
19
16
  def_delegators :@api,
20
17
  :access_token, :access_token=, :device_id, :device_id=, :homeserver, :homeserver=,
21
18
  :validate_certificate, :validate_certificate=
22
19
 
23
- def initialize(hs_url, params = {})
20
+ # @param hs_url [String,URI,Api] The URL to the Matrix homeserver, without the /_matrix/ part, or an existing Api instance
21
+ # @param client_cache [:all,:some,:none] (:all) How much data should be cached in the client
22
+ # @param params [Hash] Additional parameters on creation
23
+ # @option params [String,MXID] :user_id The user ID of the logged-in user
24
+ # @option params [Integer] :sync_filter_limit (20) Limit of timeline entries in syncs
25
+ # @see MatrixSdk::Api.new for additional usable params
26
+ def initialize(hs_url, client_cache: :all, **params)
24
27
  event_initialize
25
28
 
26
29
  params[:user_id] ||= params[:mxid] if params[:mxid]
@@ -36,7 +39,7 @@ module MatrixSdk
36
39
 
37
40
  @rooms = {}
38
41
  @users = {}
39
- @cache = params.fetch(:client_cache, :all)
42
+ @cache = client_cache
40
43
 
41
44
  @sync_token = nil
42
45
  @sync_thread = nil
@@ -54,6 +57,7 @@ module MatrixSdk
54
57
  raise ArgumentError, 'Cache value must be one of of [:all, :some, :none]' unless %i[all some none].include? @cache
55
58
 
56
59
  return unless params[:user_id]
60
+
57
61
  @mxid = params[:user_id]
58
62
  end
59
63
 
@@ -67,7 +71,15 @@ module MatrixSdk
67
71
  end
68
72
  end
69
73
 
74
+ def mxid=(id)
75
+ id = MXID.new id.to_s unless id.is_a? MXID
76
+ raise ArgumentError, 'Must be a User ID' unless id.user?
77
+
78
+ @mxid = id
79
+ end
80
+
70
81
  alias user_id mxid
82
+ alias user_id= mxid=
71
83
 
72
84
  def rooms
73
85
  @rooms.values
@@ -79,15 +91,48 @@ module MatrixSdk
79
91
  end
80
92
 
81
93
  def register_with_password(username, password)
94
+ username = username.to_s unless username.is_a?(String)
95
+ password = password.to_s unless password.is_a?(String)
96
+
97
+ raise ArgumentError, "Username can't be nil or empty" if username.nil? || username.empty?
98
+ raise ArgumentError, "Password can't be nil or empty" if password.nil? || username.empty?
99
+
82
100
  data = api.register(auth: { type: 'm.login.dummy' }, username: username, password: password)
83
101
  post_authentication(data)
84
102
  end
85
103
 
86
- def login(username, password, params = {})
104
+ def login(username, password, sync_timeout: 15, full_state: false, **params)
105
+ username = username.to_s unless username.is_a?(String)
106
+ password = password.to_s unless password.is_a?(String)
107
+
108
+ raise ArgumentError, "Username can't be nil or empty" if username.nil? || username.empty?
109
+ raise ArgumentError, "Password can't be nil or empty" if password.nil? || password.empty?
110
+
87
111
  data = api.login(user: username, password: password)
88
112
  post_authentication(data)
89
113
 
90
- sync(timeout: params.fetch(:sync_timeout, 15), full_state: params.fetch(:full_state, false)) unless params[:no_sync]
114
+ return if params[:no_sync]
115
+
116
+ sync timeout: sync_timeout,
117
+ full_state: full_state,
118
+ allow_sync_retry: params.fetch(:allow_sync_retry, nil)
119
+ end
120
+
121
+ def login_with_token(username, token, sync_timeout: 15, full_state: false, **params)
122
+ username = username.to_s unless username.is_a?(String)
123
+ token = token.to_s unless token.is_a?(String)
124
+
125
+ raise ArgumentError, "Username can't be nil or empty" if username.nil? || username.empty?
126
+ raise ArgumentError, "Token can't be nil or empty" if token.nil? || token.empty?
127
+
128
+ data = api.login(user: username, token: token, type: 'm.login.token')
129
+ post_authentication(data)
130
+
131
+ return if params[:no_sync]
132
+
133
+ sync timeout: sync_timeout,
134
+ full_state: full_state,
135
+ allow_sync_retry: params.fetch(:allow_sync_retry, nil)
91
136
  end
92
137
 
93
138
  def logout
@@ -128,10 +173,11 @@ module MatrixSdk
128
173
  def upload(content, content_type)
129
174
  data = api.media_upload(content, content_type)
130
175
  return data[:content_uri] if data.key? :content_uri
176
+
131
177
  raise MatrixUnexpectedResponseError, 'Upload succeeded, but no media URI returned'
132
178
  end
133
179
 
134
- def listen_for_events(timeout = 30, arguments = {})
180
+ def listen_for_events(timeout: 30, **arguments)
135
181
  sync(arguments.merge(timeout: timeout))
136
182
  end
137
183
 
@@ -144,6 +190,7 @@ module MatrixSdk
144
190
 
145
191
  def stop_listener_thread
146
192
  return unless @sync_thread
193
+
147
194
  @should_listen = false
148
195
  @sync_thread.join if @sync_thread.alive?
149
196
  @sync_thread = nil
@@ -151,17 +198,14 @@ module MatrixSdk
151
198
 
152
199
  private
153
200
 
154
- def listen_forever(params = {})
155
- timeout = params.fetch(:timeout, 30)
156
- params[:bad_sync_timeout] = params.fetch(:bad_sync_timeout, 5)
157
- params[:sync_interval] = params.fetch(:sync_interval, 30)
158
-
159
- bad_sync_timeout = params[:bad_sync_timeout]
201
+ def listen_forever(timeout: 30, bad_sync_timeout: 5, sync_interval: 30, **params)
202
+ orig_bad_sync_timeout = bad_sync_timeout.dup
160
203
  while @should_listen
161
204
  begin
162
- sync(timeout: timeout)
163
- bad_sync_timeout = params[:bad_sync_timeout]
164
- sleep(params[:sync_interval]) if params[:sync_interval] > 0
205
+ sync(params.merge(timeout: timeout))
206
+
207
+ bad_sync_timeout = orig_bad_sync_timeout
208
+ sleep(sync_interval) if sync_interval > 0
165
209
  rescue MatrixRequestError => ex
166
210
  logger.warn("A #{ex.class} occurred during sync")
167
211
  if ex.httpstatus >= 500
@@ -215,14 +259,27 @@ module MatrixSdk
215
259
  end
216
260
  end
217
261
 
218
- def sync(params = {})
262
+ def sync(skip_store_batch: false, **params)
219
263
  extra_params = {
220
264
  filter: sync_filter.to_json
221
265
  }
222
266
  extra_params[:since] = @next_batch unless @next_batch.nil?
223
- data = api.sync params.merge(extra_params)
224
- @next_batch = data[:next_batch]
225
267
 
268
+ attempts = 0
269
+ data = loop do
270
+ begin
271
+ break api.sync extra_params.merge(params)
272
+ rescue MatrixTimeoutError => ex
273
+ raise ex if (attempts += 1) > params.fetch(:allow_sync_retry, 0)
274
+ end
275
+ end
276
+
277
+ @next_batch = data[:next_batch] unless skip_store_batch
278
+
279
+ handle_sync_response(data)
280
+ end
281
+
282
+ def handle_sync_response(data)
226
283
  data[:presence][:events].each do |presence_update|
227
284
  fire_presence_event(MatrixEvent.new(self, presence_update))
228
285
  end
@@ -23,6 +23,14 @@ module MatrixSdk
23
23
 
24
24
  # An error raised when errors occur in the connection layer
25
25
  class MatrixConnectionError < MatrixError
26
+ def self.class_by_code(code)
27
+ return MatrixTimeoutError if code == 504
28
+
29
+ MatrixConnectionError
30
+ end
31
+ end
32
+
33
+ class MatrixTimeoutError < MatrixConnectionError
26
34
  end
27
35
 
28
36
  # An error raised when the homeserver returns an unexpected response to the client
@@ -56,7 +56,7 @@ def ignore_inspect(*symbols)
56
56
  .reject { |f| %i[#{symbols.map { |s| "@#{s}" }.join ' '}].include? f }
57
57
  .map { |f| "\#{f}=\#{instance_variable_get(f).inspect}" }.join " " }}>"
58
58
  end
59
- *, __FILE__, __LINE__ - 4
59
+ *, __FILE__, __LINE__ - 6
60
60
  end
61
61
 
62
62
  module MatrixSdk
@@ -146,6 +146,7 @@ module MatrixSdk
146
146
 
147
147
  def method_missing(method, *args)
148
148
  return event[method] if event.key? method
149
+
149
150
  super
150
151
  end
151
152
 
@@ -0,0 +1,82 @@
1
+ module MatrixSdk
2
+ class MXID
3
+ attr_accessor :sigil, :localpart, :domain, :port
4
+
5
+ # @param identifier [String] The Matrix ID string in the format of '&<localpart>:<domain>' where '&' is the sigil
6
+ def initialize(identifier)
7
+ raise ArugmentError, 'Identifier must be a String' unless identifier.is_a? String
8
+ raise ArgumentError, 'Identifier is too long' if identifier.size > 255
9
+ raise ArgumentError, 'Identifier lacks required data' unless identifier =~ %r{^([@!$+#][^:]+:[^:]+(?::\d+)?)|(\$[A-Za-z0-9+/]+)$}
10
+
11
+ @sigil = identifier[0]
12
+ @localpart, @domain, @port = identifier[1..-1].split(':')
13
+
14
+ raise ArgumentError, 'Identifier is not a valid MXID' unless valid?
15
+ end
16
+
17
+ def to_s
18
+ "#{sigil}#{localpart}#{domain ? ':' + domain : ''}"
19
+ end
20
+
21
+ # Returns the type of the ID
22
+ #
23
+ # @return [Symbol] The MXID type, one of (:user_id, :room_id, :event_id, :group_id, or :room_alias)
24
+ def type
25
+ case sigil
26
+ when '@'
27
+ :user_id
28
+ when '!'
29
+ :room_id
30
+ when '$'
31
+ :event_id
32
+ when '+'
33
+ :group_id
34
+ when '#'
35
+ :room_alias
36
+ end
37
+ end
38
+
39
+ # Checks if the ID is valid
40
+ #
41
+ # @return [Boolean] If the ID is a valid Matrix ID
42
+ def valid?
43
+ !type.nil?
44
+ end
45
+
46
+ # Check if the ID is of a user
47
+ # @return [Boolean] if the ID is of the user_id type
48
+ def user?
49
+ type == :user_id
50
+ end
51
+
52
+ # Check if the ID is of a group
53
+ # @return [Boolean] if the ID is of the group_id type
54
+ def group?
55
+ type == :group_id
56
+ end
57
+
58
+ # Check if the ID is of a room
59
+ # @return [Boolean] if the ID is of the room_id or room_alias types
60
+ def room?
61
+ type == :room_id || type == :room_alias
62
+ end
63
+
64
+ # Check if the ID is of a event
65
+ # @return [Boolean] if the ID is of the event_id type
66
+ def event?
67
+ type == :event_id
68
+ end
69
+
70
+ # Check if the ID is a room_id
71
+ # @return [Boolean] if the ID is of the room_id type
72
+ def room_id?
73
+ type == :room_id
74
+ end
75
+
76
+ # Check if the ID is a room_alias
77
+ # @return [Boolean] if the ID is of the room_alias type
78
+ def room_alias?
79
+ type == :room_alias
80
+ end
81
+ end
82
+ end
@@ -34,6 +34,7 @@ module MatrixSdk
34
34
 
35
35
  def method_missing(name, *args)
36
36
  return fetch(name) if key?(name) && args.empty?
37
+
37
38
  super
38
39
  end
39
40
  end
@@ -115,6 +115,7 @@ module MatrixSdk
115
115
 
116
116
  client.api.get_room_members(id)[:chunk].each do |chunk|
117
117
  next unless chunk [:content][:membership] == 'join'
118
+
118
119
  ensure_member(User.new(client, chunk[:state_key], display_name: chunk[:content].fetch(:displayname)))
119
120
  end
120
121
  members
@@ -149,7 +150,7 @@ module MatrixSdk
149
150
  # Possible message types as defined by the spec
150
151
  def send_html(html, body = nil, msg_type = 'm.text')
151
152
  content = {
152
- body: body ? body : html.gsub(/<\/?[^>]*>/, ''),
153
+ body: body || html.gsub(/<\/?[^>]*>/, ''),
153
154
  msgtype: msg_type,
154
155
  format: 'org.matrix.custom.html',
155
156
  formatted_body: html
@@ -338,6 +339,7 @@ module MatrixSdk
338
339
  # @note the avatar URL should be a mxc:// URI
339
340
  def set_user_profile(params = {})
340
341
  return nil unless params[:display_name] || params[:avatar_url]
342
+
341
343
  data = client.api.get_membership(id, client.mxid)
342
344
  raise "Can't set profile if you haven't joined the room" unless data[:membership] == 'join'
343
345
 
@@ -348,7 +350,21 @@ module MatrixSdk
348
350
  end
349
351
 
350
352
  def tags
351
- client.api.get_user_tags(client.mxid, id)
353
+ client.api.get_user_tags(client.mxid, id)[:tags].tap do |tag_obj|
354
+ tag_obj.instance_variable_set(:@room, self)
355
+ tag_obj.define_singleton_method(:room) do
356
+ @room
357
+ end
358
+ tag_obj.define_singleton_method(:add) do |tag, params = {}|
359
+ @room.add_tag(tag.to_s.to_sym, params)
360
+ self[tag.to_s.to_sym] = params
361
+ self
362
+ end
363
+ tag_obj.define_singleton_method(:remove) do |tag|
364
+ @room.remove_tag(tag.to_s.to_sym)
365
+ delete tag.to_s.to_sym
366
+ end
367
+ end
352
368
  end
353
369
 
354
370
  def remove_tag(tag)
@@ -458,6 +474,7 @@ module MatrixSdk
458
474
  # @return [Boolean] if the change was successful
459
475
  def modify_user_power_levels(users = nil, users_default = nil)
460
476
  return false if users.nil? && users_default.nil?
477
+
461
478
  data = client.api.get_power_levels(id)
462
479
  data[:users_default] = users_default unless users_default.nil?
463
480
 
@@ -479,6 +496,7 @@ module MatrixSdk
479
496
  # @return [Boolean] if the change was successful
480
497
  def modify_required_power_levels(events = nil, params = {})
481
498
  return false if events.nil? && (params.nil? || params.empty?)
499
+
482
500
  data = client.api.get_power_levels(id)
483
501
  data.merge!(params)
484
502
  data.delete_if { |_k, v| v.nil? }
@@ -1,3 +1,3 @@
1
1
  module MatrixSdk
2
- VERSION = '0.0.3'.freeze
2
+ VERSION = '0.0.4'.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 :MXID, 'matrix_sdk/mxid'
9
10
  autoload :Response, 'matrix_sdk/response'
10
11
  autoload :Room, 'matrix_sdk/room'
11
12
  autoload :User, 'matrix_sdk/user'
data/matrix-sdk.gemspec CHANGED
@@ -18,7 +18,10 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.add_dependency 'logging', '~> 2'
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.14'
22
- spec.add_development_dependency 'minitest', '~> 5.0'
23
- spec.add_development_dependency 'rake', '~> 10.0'
21
+ spec.add_development_dependency 'mocha'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'test-unit'
24
+
25
+ # TODO: Put this in a better location
26
+ spec.add_development_dependency 'ci_reporter_test_unit'
24
27
  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.3
4
+ version: 0.0.4
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-08-14 00:00:00.000000000 Z
11
+ date: 2019-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logging
@@ -25,47 +25,61 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bundler
28
+ name: mocha
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.14'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.14'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: minitest
42
+ name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '5.0'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '5.0'
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rake
56
+ name: test-unit
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ci_reporter_test_unit
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
67
81
  - !ruby/object:Gem::Version
68
- version: '10.0'
82
+ version: '0'
69
83
  description: ''
70
84
  email:
71
85
  - ace@haxalot.com
@@ -88,6 +102,7 @@ files:
88
102
  - lib/matrix_sdk/client.rb
89
103
  - lib/matrix_sdk/errors.rb
90
104
  - lib/matrix_sdk/extensions.rb
105
+ - lib/matrix_sdk/mxid.rb
91
106
  - lib/matrix_sdk/response.rb
92
107
  - lib/matrix_sdk/room.rb
93
108
  - lib/matrix_sdk/user.rb
@@ -113,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
128
  version: '0'
114
129
  requirements: []
115
130
  rubyforge_project:
116
- rubygems_version: 2.7.6
131
+ rubygems_version: 2.7.7
117
132
  signing_key:
118
133
  specification_version: 4
119
134
  summary: ''