lib/chatrix/client.rb
# encoding: utf-8
# frozen_string_literal: true
require 'chatrix/matrix'
require 'chatrix/users'
require 'chatrix/rooms'
require 'wisper'
module Chatrix
# A client wrapping the API in easy-to-use methods.
class Client
include Wisper::Publisher
# @return [User] The user associated with the access token.
attr_reader :me
# Initializes a new Client instance.
#
# Currently it requires a token, future versions will allow login
# with arbitrary details.
#
# @param token [String] The access token to use.
# @param id [String] The user ID of the token owner.
# @param homeserver [String,nil] Homeserver to connect to. If not set,
# the default homeserver defined in Chatrix::Matrix will be used.
def initialize(token, id, homeserver: nil)
@matrix = Matrix.new token, homeserver
@users = Users.new
@rooms = Rooms.new @users, @matrix
@me = @users.send(:get_user, id)
@rooms.on(:added) do |room|
broadcast(:room_added, room)
room.on(:invited) { |s, i| broadcast(:invited, room, s, i) }
room.timeline.on(:message) { |r, m| broadcast(:room_message, r, m) }
end
on(:disconnected) { stop_syncing }
end
# Starts syncing against the homeserver.
#
# Launches a new thread that will continously check for new events
# from the server.
#
# @see #sync! See the documentation for {#sync!} for more information
# and what happens in case of an error during sync.
def start_syncing
@sync_thread ||= Thread.new do
begin
loop { sync! }
rescue => e
broadcast(:connection_error, e)
ensure
broadcast(:disconnected)
end
end
end
# Stops syncing against the homeserver.
def stop_syncing
return unless @sync_thread.is_a? Thread
@sync_thread.exit
@sync_thread.join
rescue => e
broadcast(:stop_error, e)
ensure
@sync_thread = nil
end
# Gets the user with the specified ID or display name.
#
# @return [User,nil] Returns a User object if the user could be found,
# otherwise `nil`.
def get_user(id)
@users[id]
end
# Gets the room with the specified ID, alias, or name.
#
# @return [Room,nil] Returns a Room object if the room could be found,
# otherwise `nil`.
def get_room(id)
@rooms[id]
end
# Joins the room with the specified ID.
# @param id [String] The room ID to join.
# @return [Room] The Room instance for the joined room.
def join_room(id)
@rooms.join id
end
private
# Syncs against the server.
#
# If an API error occurs during sync, it will be rescued and broadcasted
# as `:sync_error`.
def sync!
events = @matrix.sync since: @since
process_sync events
rescue ApiError => err
broadcast(:sync_error, err)
end
# Process the sync result.
#
# @param events [Hash] The events to sync.
def process_sync(events)
return unless events.is_a? Hash
@since = events['next_batch']
broadcast(:sync, events)
@rooms.process_events events['rooms'] if events.key? 'rooms'
end
end
end