Class: MatrixSdk::Client

Inherits:
Object show all
Extended by:
Forwardable, Extensions
Includes:
Logging
Defined in:
lib/matrix_sdk/client.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Extensions

events, ignore_inspect

Methods included from Logging

#logger, #logger=

Constructor Details

#initialize(hs_url, client_cache: :all, **params) ⇒ Client

Returns a new instance of Client.

Options Hash (**params):

  • :user_id (String, MXID)

    The user ID of the logged-in user

  • :sync_filter_limit (Integer) — default: 20

    Limit of timeline entries in syncs

Raises:

  • (ArgumentError)

See Also:

  • for additional usable params


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/matrix_sdk/client.rb', line 38

def initialize(hs_url, client_cache: :all, **params)
  event_initialize

  params[:user_id] ||= params[:mxid] if params[:mxid]

  if hs_url.is_a? Api
    @api = hs_url
    params.each do |k, v|
      api.instance_variable_set("@#{k}", v) if api.instance_variable_defined? "@#{k}"
    end
  else
    @api = Api.new hs_url, params
  end

  @rooms = {}
  @users = {}
  @cache = client_cache
  @identity_server = params.fetch(:identity_server, nil)

  @sync_token = nil
  @sync_thread = nil
  @sync_filter = { room: { timeline: { limit: params.fetch(:sync_filter_limit, 20) }, state: { lazy_load_members: true } } }

  @should_listen = false
  @next_batch = nil

  @bad_sync_timeout_limit = 60 * 60

  params.each do |k, v|
    instance_variable_set("@#{k}", v) if instance_variable_defined? "@#{k}"
  end

  raise ArgumentError, 'Cache value must be one of of [:all, :some, :none]' unless %i[all some none].include? @cache

  return unless params[:user_id]

  @mxid = params[:user_id]
end

Instance Attribute Details

#apiObject (readonly)

Returns the value of attribute api.



13
14
15
# File 'lib/matrix_sdk/client.rb', line 13

def api
  @api
end

#cacheObject

Returns the value of attribute cache.



14
15
16
# File 'lib/matrix_sdk/client.rb', line 14

def cache
  @cache
end

#sync_filterObject

Returns the value of attribute sync_filter.



14
15
16
# File 'lib/matrix_sdk/client.rb', line 14

def sync_filter
  @sync_filter
end

Class Method Details

.new_for_domain(domain, **params) ⇒ Object



24
25
26
27
28
29
30
# File 'lib/matrix_sdk/client.rb', line 24

def self.new_for_domain(domain, **params)
  api = MatrixSdk::Api.new_for_domain(domain, keep_wellknown: true)
  return new(api, params) unless api.well_known.key? 'm.identity_server'

  identity_server = MatrixSdk::Api.new(api.well_known['m.identity_server']['base_url'], protocols: %i[IS])
  new(api, params.merge(identity_server: identity_server))
end

Instance Method Details

#create_room(room_alias = nil, **params) ⇒ Object



204
205
206
207
# File 'lib/matrix_sdk/client.rb', line 204

def create_room(room_alias = nil, **params)
  data = api.create_room(params.merge(room_alias: room_alias))
  ensure_room(data.room_id)
end

#find_room(room_id_or_alias, only_canonical: false) ⇒ Object

Raises:

  • (ArgumentError)


215
216
217
218
219
220
221
222
223
224
# File 'lib/matrix_sdk/client.rb', line 215

def find_room(room_id_or_alias, only_canonical: false)
  room_id_or_alias = MXID.new(room_id_or_alias.to_s) unless room_id_or_alias.is_a? MXID
  raise ArgumentError, 'Must be a room id or alias' unless %i[room_id room_alias].include? room_id_or_alias.type

  return @rooms.fetch(room_id_or_alias.to_s, nil) if room_id_or_alias.room_id?

  return @rooms.values.find { |r| r.canonical_alias == room_id_or_alias.to_s } if only_canonical

  @rooms.values.find { |r| r.aliases.include? room_id_or_alias.to_s }
end

#get_user(user_id) ⇒ Object



226
227
228
229
230
231
232
# File 'lib/matrix_sdk/client.rb', line 226

def get_user(user_id)
  if cache == :all
    @users[user_id] ||= User.new(self, user_id)
  else
    User.new(self, user_id)
  end
end

#join_room(room_id_or_alias, server_name: []) ⇒ Object



209
210
211
212
213
# File 'lib/matrix_sdk/client.rb', line 209

def join_room(room_id_or_alias, server_name: [])
  server_name = [server_name] unless server_name.is_a? Array
  data = api.join_room(room_id_or_alias, server_name: server_name)
  ensure_room(data.fetch(:room_id, room_id_or_alias))
end

#logged_in?Boolean



200
201
202
# File 'lib/matrix_sdk/client.rb', line 200

def logged_in?
  !(mxid.nil? || @api.access_token.nil?)
end

#login(username, password, sync_timeout: 15, full_state: false, **params) ⇒ Object

Raises:

  • (ArgumentError)


160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/matrix_sdk/client.rb', line 160

def (username, password, sync_timeout: 15, full_state: false, **params)
  username = username.to_s unless username.is_a?(String)
  password = password.to_s unless password.is_a?(String)

  raise ArgumentError, "Username can't be nil or empty" if username.nil? || username.empty?
  raise ArgumentError, "Password can't be nil or empty" if password.nil? || password.empty?

  data = api.(user: username, password: password)
  post_authentication(data)

  return if params[:no_sync]

  sync timeout: sync_timeout,
       full_state: full_state,
       allow_sync_retry: params.fetch(:allow_sync_retry, nil)
end

#login_with_token(username, token, sync_timeout: 15, full_state: false, **params) ⇒ Object

Raises:

  • (ArgumentError)


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/matrix_sdk/client.rb', line 177

def (username, token, sync_timeout: 15, full_state: false, **params)
  username = username.to_s unless username.is_a?(String)
  token = token.to_s unless token.is_a?(String)

  raise ArgumentError, "Username can't be nil or empty" if username.nil? || username.empty?
  raise ArgumentError, "Token can't be nil or empty" if token.nil? || token.empty?

  data = api.(user: username, token: token, type: 'm.login.token')
  post_authentication(data)

  return if params[:no_sync]

  sync timeout: sync_timeout,
       full_state: full_state,
       allow_sync_retry: params.fetch(:allow_sync_retry, nil)
end

#logoutObject



194
195
196
197
198
# File 'lib/matrix_sdk/client.rb', line 194

def logout
  api.logout
  @api.access_token = nil
  @mxid = nil
end

#mxidObject Also known as: user_id



77
78
79
80
81
# File 'lib/matrix_sdk/client.rb', line 77

def mxid
  @mxid ||= begin
    api.whoami?[:user_id] if api&.access_token
  end
end

#mxid=(id) ⇒ Object Also known as: user_id=

Raises:

  • (ArgumentError)


83
84
85
86
87
88
# File 'lib/matrix_sdk/client.rb', line 83

def mxid=(id)
  id = MXID.new id.to_s unless id.is_a? MXID
  raise ArgumentError, 'Must be a User ID' unless id.user?

  @mxid = id
end

#public_roomsObject



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/matrix_sdk/client.rb', line 93

def public_rooms
  rooms = []
  since = nil
  loop do
    data = api.get_public_rooms since: since

    data[:chunk].each do |chunk|
      rooms << Room.new(self, chunk[:room_id],
                        name: chunk[:name], topic: chunk[:topic], aliases: chunk[:aliases],
                        canonical_alias: chunk[:canonical_alias], avatar_url: chunk[:avatar_url],
                        join_rule: :public, world_readable: chunk[:world_readable]).tap do |r|
        r.instance_variable_set :@guest_access, chunk[:guest_can_join] ? :can_join : :forbidden
      end
    end

    break if data[:next_batch].nil?

    since = data.next_batch
  end

  rooms
end

#register_as_guestObject



139
140
141
142
# File 'lib/matrix_sdk/client.rb', line 139

def register_as_guest
  data = api.register(kind: :guest)
  post_authentication(data)
end

#register_with_password(username, password, full_state: true, **params) ⇒ Object

Raises:

  • (ArgumentError)


144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/matrix_sdk/client.rb', line 144

def register_with_password(username, password, full_state: true, **params)
  username = username.to_s unless username.is_a?(String)
  password = password.to_s unless password.is_a?(String)

  raise ArgumentError, "Username can't be nil or empty" if username.nil? || username.empty?
  raise ArgumentError, "Password can't be nil or empty" if password.nil? || username.empty?

  data = api.register(auth: { type: 'm.login.dummy' }, username: username, password: password)
  post_authentication(data)

  return if params[:no_sync]

  sync full_state: full_state,
       allow_sync_retry: params.fetch(:allow_sync_retry, nil)
end

#reload_rooms!Object Also known as: refresh_rooms!



126
127
128
129
130
131
132
133
134
135
136
# File 'lib/matrix_sdk/client.rb', line 126

def reload_rooms!
  return true if cache == :none

  @rooms.clear
  api.get_joined_rooms.joined_rooms.each do |id|
    r = ensure_room(id)
    r.reload!
  end

  true
end

#remove_room_alias(room_alias) ⇒ Object



234
235
236
# File 'lib/matrix_sdk/client.rb', line 234

def remove_room_alias(room_alias)
  api.remove_room_alias(room_alias)
end

#roomsObject



116
117
118
119
120
121
122
123
124
# File 'lib/matrix_sdk/client.rb', line 116

def rooms
  if @rooms.empty? && cache != :none
    api.get_joined_rooms.joined_rooms.each do |id|
      ensure_room(id)
    end
  end

  @rooms.values
end

#start_listener_thread(**params) ⇒ Object



245
246
247
248
249
250
# File 'lib/matrix_sdk/client.rb', line 245

def start_listener_thread(**params)
  @should_listen = true
  thread = Thread.new { listen_forever(params) }
  @sync_thread = thread
  thread.run
end

#stop_listener_threadObject



252
253
254
255
256
257
258
# File 'lib/matrix_sdk/client.rb', line 252

def stop_listener_thread
  return unless @sync_thread

  @should_listen = false
  @sync_thread.join if @sync_thread.alive?
  @sync_thread = nil
end

#sync(skip_store_batch: false, **params) ⇒ Object Also known as: listen_for_events



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/matrix_sdk/client.rb', line 260

def sync(skip_store_batch: false, **params)
  extra_params = {
    filter: sync_filter,
    timeout: 30
  }
  extra_params[:since] = @next_batch unless @next_batch.nil?
  extra_params.merge!(params)
  extra_params[:filter] = extra_params[:filter].to_json unless extra_params[:filter].is_a? String

  attempts = 0
  data = loop do
    begin
      break api.sync extra_params
    rescue MatrixSdk::MatrixTimeoutError => e
      raise e if (attempts += 1) >= params.fetch(:allow_sync_retry, 0)
    end
  end

  @next_batch = data[:next_batch] unless skip_store_batch

  handle_sync_response(data)
end

#upload(content, content_type) ⇒ Object



238
239
240
241
242
243
# File 'lib/matrix_sdk/client.rb', line 238

def upload(content, content_type)
  data = api.media_upload(content, content_type)
  return data[:content_uri] if data.key? :content_uri

  raise MatrixUnexpectedResponseError, 'Upload succeeded, but no media URI returned'
end