matrix_sdk 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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: ''