class Slack::RealTime::Client

def build_socket

Returns:
  • (Slack::RealTime::Socket) -
def build_socket
  raise ClientAlreadyStartedError if started?
  start = web_client.send(rtm_start_method, start_options)
  data = Slack::Messages::Message.new(start)
  @url = data.url
  @store = @store_class.new(data) if @store_class
  @socket = socket_class.new(@url, socket_options)
end

def callback(event, type)

def callback(event, type)
  callbacks = self.callbacks[type.to_s]
  return false unless callbacks
  callbacks.each do |c|
    c.call(event)
  end
  true
rescue StandardError => e
  logger.error("#{self}##{__method__}") { e }
  false
end

def close(_event)

def close(_event)
  [@socket, socket_class].each do |s|
    s.close if s.respond_to?(:close)
  end
end

def config

def config
  Config
end

def configure

def configure
  block_given? ? yield(config) : config
end

def dispatch(event)

def dispatch(event)
  return false unless event.data
  data = Slack::Messages::Message.new(JSON.parse(event.data))
  type = data.type
  return false unless type
  type = type.to_s
  logger.debug("#{self}##{__method__}") { data.to_s }
  run_handlers(type, data) if @store
  run_callbacks(type, data)
rescue StandardError => e
  logger.error("#{self}##{__method__}") { e }
  false
end

def initialize(options = {})

def initialize(options = {})
  @callbacks = Hash.new { |h, k| h[k] = [] }
  Slack::RealTime::Config::ATTRIBUTES.each do |key|
    send("#{key}=", options.key?(key) ? options[key] : Slack::RealTime.config.send(key))
  end
  @token ||= Slack.config.token
  @logger ||= (Slack::Config.logger || Slack::Logger.default)
  @web_client = Slack::Web::Client.new(token: token, logger: logger)
end

def keep_alive?

Ensure the server is running, and ping the remote server if no other messages were sent.
def keep_alive?
  # We can't ping the remote server if we aren't connected.
  return false if @socket.nil? || !@socket.connected?
  time_since_last_message = @socket.time_since_last_message
  # If the server responded within the specified time, we are okay:
  return true if time_since_last_message < websocket_ping
  # If the server has not responded for a while:
  return false if time_since_last_message > (websocket_ping * 2)
  # Kick off the next ping message:
  ping
  true
end

def on(type, &block)

def on(type, &block)
  type = type.to_s
  callbacks[type] << block
end

def open_event(_event); end

def open_event(_event); end

def restart_async

def restart_async
  logger.debug("#{self}##{__method__}")
  @socket.close
  start = web_client.send(rtm_start_method, start_options)
  data = Slack::Messages::Message.new(start)
  @url = data.url
  @store = @store_class.new(data) if @store_class
  @socket.restart_async(self, @url)
end

def rtm_start_method

def rtm_start_method
  if start_method
    start_method
  elsif @store_class && @store_class <= Slack::RealTime::Stores::Store
    :rtm_start
  else
    :rtm_connect
  end
end

def run_callbacks(type, data)

def run_callbacks(type, data)
  callbacks = self.callbacks[type]
  return false unless callbacks
  callbacks.each do |c|
    c.call(data)
  end
  true
rescue StandardError => e
  logger.error("#{self}##{__method__}") { e }
  false
end

def run_handlers(type, data)

def run_handlers(type, data)
  return unless store.class.events
  handlers = store.class.events[type.to_s]
  handlers&.each do |handler|
    store.instance_exec(data, &handler)
  end
rescue StandardError => e
  logger.error("#{self}##{__method__}") { e }
  false
end

def run_loop

def run_loop
  @socket.connect! do |driver|
    driver.on :open do |event|
      logger.debug("#{self}##{__method__}") { event.class.name }
      open_event(event)
      callback(event, :open)
    end
    driver.on :message do |event|
      logger.debug("#{self}##{__method__}") { "#{event.class}, #{event.data}" }
      dispatch(event)
    end
    driver.on :close do |event|
      logger.debug("#{self}##{__method__}") { event.class.name }
      callback(event, :close)
      close(event)
      callback(event, :closed)
    end
    # This must be called last to ensure any events are registered before invoking user code.
    @callback&.call(driver)
  end
end

def run_ping!

Check if the remote server is responsive, and if not, restart the connection.
def run_ping!
  return if keep_alive?
  logger.warn(to_s) { 'is offline' }
  restart_async
rescue Slack::Web::Api::Errors::SlackError => e
  # stop pinging if bot was uninstalled
  case e.message
  when 'account_inactive', 'invalid_auth' then
    logger.warn(to_s) { e.message }
    raise e
  end
  logger.debug("#{self}##{__method__}") { e }
rescue StandardError => e
  # disregard all ping worker failures, keep pinging
  logger.debug("#{self}##{__method__}") { e }
end

def run_ping?

def run_ping?
  !websocket_ping.nil? && websocket_ping.positive?
end

def send_json(data)

def send_json(data)
  raise ClientNotStartedError unless started?
  logger.debug("#{self}##{__method__}") { data }
  @socket.send_data(data.to_json)
end

def socket_class

def socket_class
  concurrency::Socket
end

def socket_options

def socket_options
  socket_options = {}
  socket_options[:ping] = websocket_ping if websocket_ping
  socket_options[:proxy] = websocket_proxy if websocket_proxy
  socket_options[:logger] = logger
  socket_options
end

def start!(&block)

Start RealTime client and block until it disconnects.
def start!(&block)
  @callback = block if block_given?
  build_socket
  @socket.start_sync(self)
end

def start_async(&block)

The RealTime::Client will run in the background.
Start RealTime client and return immediately.
def start_async(&block)
  @callback = block if block_given?
  build_socket
  @socket.start_async(self)
end

def started?

def started?
  @socket&.connected?
end

def stop!

def stop!
  raise ClientNotStartedError unless started?
  @socket&.disconnect!
end

def to_s

def to_s
  if store&.team
    "id=#{store.team.id}, name=#{store.team.name}, domain=#{store.team.domain}"
  else
    super
  end
end

def websocket_ping_timer

def websocket_ping_timer
  websocket_ping / 2
end