class WSClient

Attributes

dead[R]
driver[R]
handler[RW]
in_rooms[R]
thread[R]
url[R]

Public Class Methods

new(url, cookies, bot, server, message_log: 'ws_messages.log', error_log: 'ws_errors.log', info_log: 'ws_info.log', dev_log: 'ws_dev.log') click to toggle source
# File lib/chatx/websocket.rb, line 5
def initialize(url, cookies, bot, server, message_log: 'ws_messages.log', error_log: 'ws_errors.log', info_log: 'ws_info.log', dev_log: 'ws_dev.log')
  # Setup loggers
  @message_logger = Logger.new(message_log) if message_log
  @error_logger = Logger.new(error_log) if error_log
  @info_logger = Logger.new(info_log) if info_log
  @dev_logger = Logger.new(dev_log) if dev_log

  @bot = bot
  @in_rooms = {rooms: [], last_update: Time.now}
  @server = server

  # Get WS(S) URI
  @uri = URI.parse(url)
  @url = "ws#{@uri.scheme.split("")[4]}://#{@uri.host}#{@uri.path}?#{@uri.query}"

  # Setup handler (the action that's executed on message)
  @handler = handler

  # Auto-restart unless you don't
  @restart = true
  @dev_logger.info "Set @restart to #{@restart}"

  setup(cookies: cookies, origin: "https://chat.#{@server}.com")
end

Public Instance Methods

close() click to toggle source
# File lib/chatx/websocket.rb, line 39
def close
  @info_logger.warn "Was told to close. Was sad."
  @dead = true
  @driver.close
  @socket.is_a?(TCPSocket) ? @socket.shutdown : @socket.sysclose
  @info_logger.info "Closed sucessfully"
rescue IOError, Errno::ENOTCONN => e
  @logger.error "Recieved #{e.class} trying to close websocket. Ignoring..."
end
send(message) click to toggle source
# File lib/chatx/websocket.rb, line 30
def send(message)
  @message_logger.info(message)
  @driver.text(message)
end
write(data) click to toggle source
# File lib/chatx/websocket.rb, line 35
def write(data)
  @socket.write(data)
end

Private Instance Methods

initialize_driver(cookies: nil, origin: nil) click to toggle source
# File lib/chatx/websocket.rb, line 71
def initialize_driver(cookies: nil, origin: nil)
  @driver = WebSocket::Driver.client(self)
  @driver.add_extension PermessageDeflate
  @driver.set_header "Cookies", cookies if cookies
  origin = origin || "#{@uri.scheme}://#{@uri.host.split('.')[-2..-1].join('.')}"
  @driver.set_header "Origin", origin

  @info_logger.info "Creating new driver with origin: #{origin} and with#{'out' if !cookies} cookies"

  @driver.on :connect, ->(_e) do
    @info_logger.info "Sucessfully connected!"
  end

  @driver.on :open, ->(e) do
    @info_logger.info "WebSocket is open!"
  end

  @driver.on :message do |e|
    @message_logger.info(e.data)
    @bot.handle(JSON.parse(e.data), server: @server)
    @in_rooms = {rooms: JSON.parse(e.data).keys.map { |k| k[1..-1].to_i }, last_updated: Time.now}
  end

  @driver.on :close, ->(_e) do
    @info_logger.info "WebSocket driver is closing."
    if @restart
      restart
    end
  end

  @driver.on :error, ->(e) { @error_logger.error e }

  @driver.start
end
initialize_socket() click to toggle source
# File lib/chatx/websocket.rb, line 57
def initialize_socket
  if @uri.scheme[-1] == 's'
    @socket = TCPSocket.new(@uri.host, 443)
    @info_logger.info "Opened TCP socket for (port 443) #{@uri} (#{@socket})"
    @socket = OpenSSL::SSL::SSLSocket.new(@socket)
    @socket.connect
    @info_logger.info "Upgrade TCP socket to SSL socket socket for #{@uri} (#{@socket})"
    @info_logger.info "Current socket state: #{@socket.state}"
  else
    @socket = TCPSocket.new(@uri.host, 80)
    @info_logger.info "Opened TCP socket for (port 80) #{@uri} (#{@socket})"
  end
end
launch_thread() click to toggle source
# File lib/chatx/websocket.rb, line 115
def launch_thread
  # @info_logger.info "Waiting for old thread to complete..." if @thread
  # @thread.join if @thread
  # @info_logger.info "Starting new thread!"
  @dead = false
  @thread = Thread.new do
    trap("SIGINT") do
      @restart = false
      @dead = true
      close
      Thread.exit
    end
    begin
      parse(@socket.is_a?(TCPSocket) ? @socket.recv(1) : @socket.sysread(1)) until @dead
    rescue IOError, SystemCallError => e
      @info_logger.warn "Recieved #{e} closing TCP socket. You shouldn't be worried :)"
    end
    @info_logger.warn "Left TCPSocket.recv loop. If you're reading this, panic."
  end
end
parse(data) click to toggle source
# File lib/chatx/websocket.rb, line 111
def parse(data)
  @driver.parse(data)
end
restart() click to toggle source
# File lib/chatx/websocket.rb, line 106
def restart
  @info_logger.info "Attempting ro rejoin rooms #{@in_rooms[:rooms]}"
  @bot.join_rooms(@in_rooms[:rooms])
end
setup(cookies: nil, origin: nil) click to toggle source
# File lib/chatx/websocket.rb, line 51
def setup(cookies: nil, origin: nil)
  initialize_socket
  initialize_driver(cookies: cookies, origin: origin)
  launch_thread
end