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 +4 -4
- data/.gitlab-ci.yml +11 -7
- data/.rubocop.yml +5 -1
- data/CHANGELOG.md +15 -0
- data/Rakefile +5 -0
- data/examples/simple_client.rb +49 -2
- data/lib/matrix_sdk/api.rb +273 -27
- data/lib/matrix_sdk/client.rb +77 -20
- data/lib/matrix_sdk/errors.rb +8 -0
- data/lib/matrix_sdk/extensions.rb +2 -1
- data/lib/matrix_sdk/mxid.rb +82 -0
- data/lib/matrix_sdk/response.rb +1 -0
- data/lib/matrix_sdk/room.rb +20 -2
- data/lib/matrix_sdk/version.rb +1 -1
- data/lib/matrix_sdk.rb +1 -0
- data/matrix-sdk.gemspec +6 -3
- metadata +33 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39fdb05386da317f2810f25e668ae14bdd261c807bafc61056fa09dd1d6a8175
|
4
|
+
data.tar.gz: 88b32840ca73b6588f36e35edcccac15e721b071c69a60c6cfc383dceaf67e5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
17
|
-
- rubocop
|
16
|
+
- gem install rubocop -N
|
17
|
+
- rubocop lib
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
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:
|
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
data/examples/simple_client.rb
CHANGED
@@ -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
|
-
|
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,
|
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)
|
data/lib/matrix_sdk/api.rb
CHANGED
@@ -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'
|
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
|
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__
|
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
|
-
|
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
|
-
|
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/#{
|
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
|
-
|
456
|
-
|
457
|
-
|
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
|
-
|
467
|
-
|
468
|
-
|
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
|
-
|
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)
|
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
|
data/lib/matrix_sdk/client.rb
CHANGED
@@ -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
|
-
|
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 =
|
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,
|
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
|
-
|
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
|
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(
|
155
|
-
|
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
|
-
|
164
|
-
|
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(
|
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
|
data/lib/matrix_sdk/errors.rb
CHANGED
@@ -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__ -
|
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
|
data/lib/matrix_sdk/response.rb
CHANGED
data/lib/matrix_sdk/room.rb
CHANGED
@@ -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
|
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? }
|
data/lib/matrix_sdk/version.rb
CHANGED
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 '
|
22
|
-
spec.add_development_dependency '
|
23
|
-
spec.add_development_dependency '
|
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.
|
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:
|
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:
|
28
|
+
name: mocha
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
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: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
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: '
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: test-unit
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
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: '
|
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.
|
131
|
+
rubygems_version: 2.7.7
|
117
132
|
signing_key:
|
118
133
|
specification_version: 4
|
119
134
|
summary: ''
|