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