Class: MatrixSdk::Client

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logging

#logger

Constructor Details

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

Returns a new instance of Client.

Parameters:

  • hs_url (String, URI, Api)

    The URL to the Matrix homeserver, without the /_matrix/ part, or an existing Api instance

  • client_cache (:all, :some, :none) (defaults to: :all)

    (:all) How much data should be cached in the client

  • params (Hash)

    Additional parameters on creation

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


37
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
# File 'lib/matrix_sdk/client.rb', line 37

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.



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

def api
  @api
end

#cacheObject

Returns the value of attribute cache.



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

def cache
  @cache
end

#sync_filterObject

Returns the value of attribute sync_filter.



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

def sync_filter
  @sync_filter
end

Class Method Details

.new_for_domain(domain, **params) ⇒ Object



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

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



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

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)


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

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



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

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) ⇒ Object



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

def join_room(room_id_or_alias)
  data = api.join_room(room_id_or_alias)
  ensure_room(data.fetch(:room_id, room_id_or_alias))
end

#logged_in?Boolean

Returns:

  • (Boolean)


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

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

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

Raises:

  • (ArgumentError)


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

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)


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

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



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

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

#mxidObject Also known as: user_id



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

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

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

Raises:

  • (ArgumentError)


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

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



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

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



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

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)


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

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!



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

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



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

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

#roomsObject



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

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



243
244
245
246
247
248
# File 'lib/matrix_sdk/client.rb', line 243

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

#stop_listener_threadObject



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

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



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

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 # rubocop:disable Style/RedundantBegin
      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



236
237
238
239
240
241
# File 'lib/matrix_sdk/client.rb', line 236

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