Class: MatrixSdk::Api

Inherits:
Object
  • Object
show all
Defined in:
lib/matrix_sdk/api.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(homeserver, params = {}) ⇒ Api



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/matrix_sdk/api.rb', line 15

def initialize(homeserver, params = {})
  @homeserver = homeserver
  @homeserver = URI.parse(@homeserver.to_s) unless @homeserver.is_a? URI
  if @homeserver.path.end_with? '_matrix/'
    @homeserver.path = begin
      split = @homeserver.path.rpartition '_matrix/'
      (split[(split.find_index '_matrix/')] = '/') rescue nil
      split.join
    end
  end
  raise 'Please use the base URL for your HS (without /_matrix/)' if @homeserver.path.include? '/_matrix/'

  @access_token = params.fetch(:access_token, nil)
  @device_id = params.fetch(:device_id, nil)
  @validate_certificate = params.fetch(:validate_certificate, false)
  @transaction_id = params.fetch(:transaction_id, 0)
  @backoff_time = params.fetch(:backoff_time, 5000)

  (user: @homeserver.user, password: @homeserver.password) if @homeserver.user && @homeserver.password && !@access_token && !params[:skip_login]
  @homeserver.userinfo = '' unless params[:skip_login]
end

Instance Attribute Details

#access_tokenObject

Returns the value of attribute access_token.



10
11
12
# File 'lib/matrix_sdk/api.rb', line 10

def access_token
  @access_token
end

#device_idObject

Returns the value of attribute device_id.



10
11
12
# File 'lib/matrix_sdk/api.rb', line 10

def device_id
  @device_id
end

#homeserverObject

Returns the value of attribute homeserver.



11
12
13
# File 'lib/matrix_sdk/api.rb', line 11

def homeserver
  @homeserver
end

#validate_certificateObject

Returns the value of attribute validate_certificate.



11
12
13
# File 'lib/matrix_sdk/api.rb', line 11

def validate_certificate
  @validate_certificate
end

Instance Method Details

#add_user_tag(user_id, room_id, tag, params = {}) ⇒ Object



289
290
291
292
293
294
295
296
297
# File 'lib/matrix_sdk/api.rb', line 289

def add_user_tag(user_id, room_id, tag, params = {})
  if params[:body]
    content = params[:body]
  else
    content = {}
    content[:order] = params[:order] if params.key? :order
  end
  request(:put, :client_r0, "/user/#{user_id}/rooms/#{room_id}/tags/#{tag}", body: content)
end

#api_versionsObject



54
55
56
# File 'lib/matrix_sdk/api.rb', line 54

def api_versions
  request(:get, :client, '/versions')
end

#ban_user(room_id, user_id, params = {}) ⇒ Object



266
267
268
269
270
271
272
# File 'lib/matrix_sdk/api.rb', line 266

def ban_user(room_id, user_id, params = {})
  content = {
    user_id: user_id,
    reason: params[:reason] || ''
  }
  request(:post, :client_r0, "/rooms/#{room_id}/ban", body: content)
end

#create_filter(user_id, filter_params) ⇒ Object



323
324
325
# File 'lib/matrix_sdk/api.rb', line 323

def create_filter(user_id, filter_params)
  request(:post, :client_r0, "/user/#{user_id}/filter", body: filter_params)
end

#create_room(params = {}) ⇒ Object



98
99
100
101
102
103
104
105
106
# File 'lib/matrix_sdk/api.rb', line 98

def create_room(params = {})
  content = {
    visibility: params.fetch(:visibility, :public)
  }
  content[:room_alias_name] = params[:room_alias] if params[:room_alias]
  content[:invite] = [params[:invite]].flatten if params[:invite]

  request(:post, :client_r0, '/createRoom', content)
end

#forget_room(room_id) ⇒ Object



236
237
238
# File 'lib/matrix_sdk/api.rb', line 236

def forget_room(room_id)
  request(:post, :client_r0, "/rooms/#{room_id}/forget")
end

#get_account_data(user_id, type) ⇒ Object



299
300
301
# File 'lib/matrix_sdk/api.rb', line 299

def (user_id, type)
  request(:get, :client_r0, "/user/#{user_id}/account_data/#{type}")
end

#get_avatar_url(user_id) ⇒ Object



342
343
344
# File 'lib/matrix_sdk/api.rb', line 342

def get_avatar_url(user_id)
  request(:get, :client_r0, "/profile/#{user_id}/avatar_url")
end

#get_display_name(user_id) ⇒ Object



331
332
333
# File 'lib/matrix_sdk/api.rb', line 331

def get_display_name(user_id)
  request(:get, :client_r0, "/profile/#{user_id}/displayname")
end

#get_download_url(mxcurl) ⇒ Object



353
354
355
356
357
358
359
360
# File 'lib/matrix_sdk/api.rb', line 353

def get_download_url(mxcurl)
  mxcurl = URI.parse(mxcurl.to_s) unless mxcurl.is_a? URI
  raise 'Not a mxc:// URL' unless mxcurl.is_a? URI::MATRIX

  homeserver.dup.tap do |u|
    u.path = "/_matrix/media/r0/download/#{mxcurl.full_path}"
  end
end

#get_filter(user_id, filter_id) ⇒ Object



319
320
321
# File 'lib/matrix_sdk/api.rb', line 319

def get_filter(user_id, filter_id)
  request(:get, :client_r0, "/user/#{user_id}/filter/#{filter_id}")
end

#get_membership(room_id, user_id) ⇒ Object



251
252
253
# File 'lib/matrix_sdk/api.rb', line 251

def get_membership(room_id, user_id)
  request(:get, :client_r0, "/rooms/#{room_id}/state/m.room.member/#{user_id}")
end

#get_power_levels(room_id) ⇒ Object



223
224
225
# File 'lib/matrix_sdk/api.rb', line 223

def get_power_levels(room_id)
  request(:get, :client_r0, "/rooms/#{room_id}/state/m.room.power_levels")
end

#get_room_account_data(user_id, room_id, type) ⇒ Object



307
308
309
# File 'lib/matrix_sdk/api.rb', line 307

def (user_id, room_id, type)
  request(:get, :client_r0, "/user/#{user_id}/rooms/#{room_id}/account_data/#{type}")
end

#get_room_id(room_alias) ⇒ Object



362
363
364
# File 'lib/matrix_sdk/api.rb', line 362

def get_room_id(room_alias)
  request(:get, :client_r0, "/directory/room/#{room_alias}")
end

#get_room_members(room_id) ⇒ Object



377
378
379
# File 'lib/matrix_sdk/api.rb', line 377

def get_room_members(room_id)
  request(:get, :client_r0, "/rooms/#{room_id}/members")
end

#get_room_messages(room_id, token, direction, params = {}) ⇒ Object



189
190
191
192
193
194
195
196
197
198
199
# File 'lib/matrix_sdk/api.rb', line 189

def get_room_messages(room_id, token, direction, params = {})
  query = {
    roomId: room_id,
    from: token,
    dir: direction,
    limit: params.fetch(:limit, 10)
  }
  query[:to] = params[:to] if params.key? :to

  request(:get, :client_r0, "/rooms/#{room_id}/messages", query: query)
end

#get_room_name(room_id) ⇒ Object



201
202
203
# File 'lib/matrix_sdk/api.rb', line 201

def get_room_name(room_id)
  request(:get, :client_r0, "/rooms/#{room_id}/state/m.room.name")
end

#get_room_state(room_id) ⇒ Object



315
316
317
# File 'lib/matrix_sdk/api.rb', line 315

def get_room_state(room_id)
  request(:get, :client_r0, "/rooms/#{room_id}/state")
end

#get_room_topic(room_id) ⇒ Object



212
213
214
# File 'lib/matrix_sdk/api.rb', line 212

def get_room_topic(room_id)
  request(:get, :client_r0, "/rooms/#{room_id}/state/m.room.topic")
end

#get_user_tags(user_id, room_id) ⇒ Object



281
282
283
# File 'lib/matrix_sdk/api.rb', line 281

def get_user_tags(user_id, room_id)
  request(:get, :client_r0, "/user/#{user_id}/rooms/#{room_id}/tags")
end

#invite_user(room_id, user_id) ⇒ Object



240
241
242
243
244
245
# File 'lib/matrix_sdk/api.rb', line 240

def invite_user(room_id, user_id)
  content = {
    user_id: user_id
  }
  request(:post, :client_r0, "/rooms/#{room_id}/invite", body: content)
end

#join_room(id_or_alias) ⇒ Object



108
109
110
# File 'lib/matrix_sdk/api.rb', line 108

def join_room(id_or_alias)
  request(:post, :client_r0, "/join/#{CGI.escape id_or_alias}")
end

#kick_user(room_id, user_id, params = {}) ⇒ Object



247
248
249
# File 'lib/matrix_sdk/api.rb', line 247

def kick_user(room_id, user_id, params = {})
  set_membership(room_id, user_id, 'leave', params)
end

#leave_room(room_id) ⇒ Object



232
233
234
# File 'lib/matrix_sdk/api.rb', line 232

def leave_room(room_id)
  request(:post, :client_r0, "/rooms/#{room_id}/leave")
end

#loggerObject



37
38
39
# File 'lib/matrix_sdk/api.rb', line 37

def logger
  @logger ||= Logging.logger[self.class.name]
end

#login(params = {}) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/matrix_sdk/api.rb', line 77

def (params = {})
  options = {}
  options[:store_token] = params.delete(:store_token) { true }
  options[:store_device_id] = params.delete(:store_device_id) { true }

  data = {
    type: params.delete(:login_type) { 'm.login.password' },
    initial_device_display_name: params.delete(:initial_device_display_name) { user_agent }
  }.merge params
  data[:device_id] = device_id if device_id

  request(:post, :client_r0, '/login', body: data).tap do |resp|
    @access_token = resp[:token] if resp[:token] && options[:store_token]
    @device_id = resp[:device_id] if resp[:device_id] && options[:store_device_id]
  end
end

#logoutObject



94
95
96
# File 'lib/matrix_sdk/api.rb', line 94

def logout
  request(:post, :client_r0, '/logout')
end

#media_upload(content, content_type) ⇒ Object



327
328
329
# File 'lib/matrix_sdk/api.rb', line 327

def media_upload(content, content_type)
  request(:post, :media_r0, '/upload', body: content, headers: { 'content-type' => content_type })
end

#redact_event(room_id, event_type, params = {}) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/matrix_sdk/api.rb', line 129

def redact_event(room_id, event_type, params = {})
  query = {}
  query[:ts] = params[:timestamp].to_i if params.key? :timestamp

  content = {}
  content[:reason] = params[:reason] if params[:reason]

  txn_id = transaction_id
  txn_id = params.fetch(:txn_id, "#{txn_id}#{Time.now.to_i}")

  request(:put, :client_r0, "/rooms/#{room_id}/redact/#{event_type}/#{txn_id}", body: content, query: query)
end

#register(params = {}) ⇒ Object



71
72
73
74
75
# File 'lib/matrix_sdk/api.rb', line 71

def register(params = {})
  kind = params.delete(:kind) { 'user' }

  request(:post, :client_r0, '/register', body: params, query: { kind: kind })
end

#remove_room_alias(room_alias) ⇒ Object



373
374
375
# File 'lib/matrix_sdk/api.rb', line 373

def remove_room_alias(room_alias)
  request(:delete, :client_r0, "/directory/room/#{room_alias}")
end

#remove_user_tag(user_id, room_id, tag) ⇒ Object



285
286
287
# File 'lib/matrix_sdk/api.rb', line 285

def remove_user_tag(user_id, room_id, tag)
  request(:delete, :client_r0, "/user/#{user_id}/rooms/#{room_id}/tags/#{tag}")
end

#request(method, api, path, options = {}) ⇒ Object



400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
# File 'lib/matrix_sdk/api.rb', line 400

def request(method, api, path, options = {})
  url = homeserver.dup.tap do |u|
    u.path = api_to_path(api) + path
    u.query = [u.query, options[:query].map { |k, v| "#{k}#{"=#{v}" unless v.nil?}" }].flatten.reject(&:nil?).join('&') if options[:query]
    u.query = nil if u.query.nil? || u.query.empty?
  end
  request = Net::HTTP.const_get(method.to_s.capitalize.to_sym).new url.request_uri
  request.body = options[:body] if options.key? :body
  request.body = request.body.to_json if options.key?(:body) && !request.body.is_a?(String)
  request.body_stream = options[:body_stream] if options.key? :body_stream

  request.content_type = 'application/json' if request.body || request.body_stream

  request['authorization'] = "Bearer #{access_token}" if access_token
  request['user-agent'] = user_agent
  if options.key? :headers
    options[:headers].each do |h, v|
      request[h.to_s.downcase] = v
    end
  end

  failures = 0
  loop do
    raise MatrixConnectionError, "Server still too busy to handle request after #{failures} attempts, try again later" if failures >= 10

    print_http(request)
    response = http.request request
    print_http(response)
    data = JSON.parse(response.body, symbolize_names: true) rescue nil

    if response.is_a? Net::HTTPTooManyRequests
      failures += 1
      waittime = data[:retry_after_ms] || data[:error][:retry_after_ms] || @backoff_time
      sleep(waittime.to_f / 1000.0)
      next
    end

    return data if response.is_a? Net::HTTPSuccess
    raise MatrixRequestError.new(data, response.code) if data
    raise MatrixConnectionError, response
  end
end

#send_content(room_id, url, name, msg_type, params = {}) ⇒ Object



142
143
144
145
146
147
148
149
150
151
# File 'lib/matrix_sdk/api.rb', line 142

def send_content(room_id, url, name, msg_type, params = {})
  content = {
    url: url,
    msgtype: msg_type,
    body: name,
    info: params.delete(:extra_information) { {} }
  }

  send_message_event(room_id, 'm.room.message', content, params)
end

#send_emote(room_id, emote, params = {}) ⇒ Object



173
174
175
176
177
178
179
# File 'lib/matrix_sdk/api.rb', line 173

def send_emote(room_id, emote, params = {})
  content = {
    msgtype: params.delete(:msg_type) { 'm.emote' },
    body: emote
  }
  send_message_event(room_id, 'm.room.message', content, params)
end

#send_location(room_id, geo_uri, name, params = {}) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
# File 'lib/matrix_sdk/api.rb', line 153

def send_location(room_id, geo_uri, name, params = {})
  content = {
    geo_uri: geo_uri,
    msgtype: 'm.location',
    body: name
  }
  content[:thumbnail_url] = params.delete(:thumbnail_url) if params.key? :thumbnail_url
  content[:thumbnail_info] = params.delete(:thumbnail_info) if params.key? :thumbnail_info

  send_message_event(room_id, 'm.room.message', content, params)
end

#send_message(room_id, message, params = {}) ⇒ Object



165
166
167
168
169
170
171
# File 'lib/matrix_sdk/api.rb', line 165

def send_message(room_id, message, params = {})
  content = {
    msgtype: params.delete(:msg_type) { 'm.text' },
    body: message
  }
  send_message_event(room_id, 'm.room.message', content, params)
end

#send_message_event(room_id, event_type, content, params = {}) ⇒ Object



119
120
121
122
123
124
125
126
127
# File 'lib/matrix_sdk/api.rb', line 119

def send_message_event(room_id, event_type, content, params = {})
  query = {}
  query[:ts] = params[:timestamp].to_i if params.key? :timestamp

  txn_id = transaction_id
  txn_id = params.fetch(:txn_id, "#{txn_id}#{Time.now.to_i}")

  request(:put, :client_r0, "/rooms/#{room_id}/send/#{event_type}/#{txn_id}", body: content, query: query)
end

#send_notice(room_id, notice, params = {}) ⇒ Object



181
182
183
184
185
186
187
# File 'lib/matrix_sdk/api.rb', line 181

def send_notice(room_id, notice, params = {})
  content = {
    msgtype: params.delete(:msg_type) { 'm.notice' },
    body: notice
  }
  send_message_event(room_id, 'm.room.message', content, params)
end

#send_state_event(room_id, event_type, content, params = {}) ⇒ Object



112
113
114
115
116
117
# File 'lib/matrix_sdk/api.rb', line 112

def send_state_event(room_id, event_type, content, params = {})
  query = {}
  query[:ts] = params[:timestamp].to_i if params.key? :timestamp

  request(:put, :client_r0, "/rooms/#{room_id}/state/#{event_type}#{"/#{params[:state_key]}" if params.key? :state_key}", body: content, query: query)
end

#set_account_data(user_id, type, account_data) ⇒ Object



303
304
305
# File 'lib/matrix_sdk/api.rb', line 303

def (user_id, type, )
  request(:put, :client_r0, "/user/#{user_id}/account_data/#{type}", body: )
end

#set_avatar_url(user_id, url) ⇒ Object



346
347
348
349
350
351
# File 'lib/matrix_sdk/api.rb', line 346

def set_avatar_url(user_id, url)
  content = {
    avatar_url: url
  }
  request(:put, :client_r0, "/profile/#{user_id}/avatar_url", body: content)
end

#set_display_name(user_id, display_name) ⇒ Object



335
336
337
338
339
340
# File 'lib/matrix_sdk/api.rb', line 335

def set_display_name(user_id, display_name)
  content = {
    display_name: display_name
  }
  request(:put, :client_r0, "/profile/#{user_id}/displayname", body: content)
end

#set_guest_access(room_id, guest_access) ⇒ Object



388
389
390
391
392
393
394
# File 'lib/matrix_sdk/api.rb', line 388

def set_guest_access(room_id, guest_access)
  # raise ArgumentError, '`guest_access` must be one of [:can_join, :forbidden]' unless %i[can_join forbidden].include? guest_access
  content = {
    guest_access: guest_access
  }
  send_state_event(room_id, 'm.room.guest_access', content)
end

#set_join_rule(room_id, join_rule) ⇒ Object



381
382
383
384
385
386
# File 'lib/matrix_sdk/api.rb', line 381

def set_join_rule(room_id, join_rule)
  content = {
    join_rule: join_rule
  }
  send_state_event(room_id, 'm.room.join_rules', content)
end

#set_membership(room_id, user_id, membership, params = {}) ⇒ Object



255
256
257
258
259
260
261
262
263
264
# File 'lib/matrix_sdk/api.rb', line 255

def set_membership(room_id, user_id, membership, params = {})
  content = {
    membership: membership,
    reason: params.delete(:reason) { '' }
  }
  content[:displayname] = params.delete(:displayname) if params.key? :displayname
  content[:avatar_url] = params.delete(:avatar_url) if params.key? :avatar_url

  send_state_event(room_id, 'm.room.member', content, params.merge(state_key: user_id))
end

#set_power_levels(room_id, content) ⇒ Object



227
228
229
230
# File 'lib/matrix_sdk/api.rb', line 227

def set_power_levels(room_id, content)
  content[:events] = {} unless content.key? :events
  send_state_event(room_id, 'm.room.power_levels', content)
end

#set_room_account_data(user_id, room_id, type, account_data) ⇒ Object



311
312
313
# File 'lib/matrix_sdk/api.rb', line 311

def (user_id, room_id, type, )
  request(:put, :client_r0, "/user/#{user_id}/rooms/#{room_id}/account_data/#{type}", body: )
end

#set_room_alias(room_id, room_alias) ⇒ Object



366
367
368
369
370
371
# File 'lib/matrix_sdk/api.rb', line 366

def set_room_alias(room_id, room_alias)
  content = {
    room_id: room_id
  }
  request(:put, :client_r0, "/directory/room/#{room_alias}", body: content)
end

#set_room_name(room_id, name, params = {}) ⇒ Object



205
206
207
208
209
210
# File 'lib/matrix_sdk/api.rb', line 205

def set_room_name(room_id, name, params = {})
  content = {
    name: name
  }
  send_state_event(room_id, 'm.room.name', content, params)
end

#set_room_topic(room_id, topic, params = {}) ⇒ Object



216
217
218
219
220
221
# File 'lib/matrix_sdk/api.rb', line 216

def set_room_topic(room_id, topic, params = {})
  content = {
    topic: topic
  }
  send_state_event(room_id, 'm.room.topic', content, params)
end

#sync(params = {}) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/matrix_sdk/api.rb', line 58

def sync(params = {})
  query = {
    timeout: 30.0
  }.merge(params).select do |k, _v|
    i[since timeout filter full_state set_presence].include? k
  end

  query[:timeout] = ((query[:timeout] || 30) * 1000).to_i
  query[:timeout] = params.delete(:timeout_ms).to_i if params.key? :timeout_ms

  request(:get, :client_r0, '/sync', query: query)
end

#unban_user(room_id, user_id) ⇒ Object



274
275
276
277
278
279
# File 'lib/matrix_sdk/api.rb', line 274

def unban_user(room_id, user_id)
  content = {
    user_id: user_id
  }
  request(:post, :client_r0, "/rooms/#{room_id}/unban", body: content)
end

#whoami?Boolean



396
397
398
# File 'lib/matrix_sdk/api.rb', line 396

def whoami?
  request(:get, :client_r0, '/account/whoami')
end