class Slack::RtmApi2::Client

Constants

VALID

Attributes

stop[RW]

Public Class Methods

new(conf = {}) click to toggle source
# File lib/slack/rtmapi2/client.rb, line 12
def initialize(conf = {})
  @websocket_url = conf.fetch(:websocket_url)
  @url = init_url @websocket_url
  @socket = conf[:socket]
  @driver = conf[:websocket_driver]
  @msg_queue = conf[:msg_queue] || []
  @has_been_init = false
  @stop = false
  @reading = false
  @callbacks = {}
end

Public Instance Methods

connected?() click to toggle source
# File lib/slack/rtmapi2/client.rb, line 85
def connected?
  @connected || false
end
init() click to toggle source

This init has been delayed because the SSL handshake is a blocking and expensive call

# File lib/slack/rtmapi2/client.rb, line 40
def init
  return if @has_been_init

  @socket = init_socket(@socket)
  @socket.connect # costly and blocking !

  internalWrapper = (Struct.new :url, :socket do
    def write(*args)
      self.socket.write(*args)
    end
  end).new @url.to_s, @socket

  # this, also, is costly and blocking
  @driver = WebSocket::Driver.client internalWrapper
  @driver.on :open do
    @connected = true
    unless @callbacks[:open].nil?
      @callbacks[:open].call
    end
  end

  @driver.on :error do |event|
    @connected = false
    unless @callbacks[:error].nil?
      @callbacks[:error].call event.message
    end
  end

  @driver.on :message do |event|
    data = JSON.parse event.data
    unless @callbacks[:message].nil?
      @callbacks[:message].call data
    end
  end

  @driver.on :close do |event|
    unless @callbacks[:close].nil?
      @callbacks[:close].call event.code, event.reason
    end
  end

  @driver.start
  @has_been_init = true
end
inner_loop() click to toggle source

All the polling work is done here

# File lib/slack/rtmapi2/client.rb, line 103
def inner_loop
  return if @stop
  read_socket unless @reading
  @msg_queue.each { |msg| @driver.text msg }
  @msg_queue.clear
  sleep 0.1
end
main_loop() click to toggle source

A dumb simple main loop.

# File lib/slack/rtmapi2/client.rb, line 112
def main_loop
  init
  loop do
    inner_loop
  end
end
on(type, &block) click to toggle source
# File lib/slack/rtmapi2/client.rb, line 25
def on(type, &block)
  unless VALID.include? type
    raise ArgumentError.new "Client#on accept one of #{VALID.inspect}"
  end

  @callbacks[type] = block
end
read_socket() click to toggle source
# File lib/slack/rtmapi2/client.rb, line 89
def read_socket
  @reading = true
  tries = 2
  begin
    data = @socket.read_nonblock 4096
  rescue OpenSSL::SSL::SSLErrorWaitReadable
    tries -= 1
    retry if tries > 0
  end
  @driver.parse data unless data.nil? || data.empty?
  @reading = false
end
send(data) click to toggle source
# File lib/slack/rtmapi2/client.rb, line 33
def send(data)
  data[:id] ||= SecureRandom.random_number 9_999_999
  @msg_queue << data.to_json
end
write(*args) click to toggle source
# File lib/slack/rtmapi2/client.rb, line 47
def write(*args)
  self.socket.write(*args)
end

Private Instance Methods

init_socket(socket = nil) click to toggle source
# File lib/slack/rtmapi2/client.rb, line 130
def init_socket(socket = nil)
  if socket.kind_of? OpenSSL::SSL::SSLSocket
    socket
  elsif socket.kind_of? TCPSocket
    OpenSSL::SSL::SSLSocket.new socket
  else
    OpenSSL::SSL::SSLSocket.new TCPSocket.new @url.host, 443
  end
end
init_url(url) click to toggle source
# File lib/slack/rtmapi2/client.rb, line 121
def init_url(url)
  url = if url.kind_of? URI then url else URI(url) end
  if url.scheme != 'wss'
    raise ArgumentError.new "config[:websocket_url] should be a valid websocket secure url !"
  end

  url
end