class Ferris::RTM
Constants
- HTTPS_PORT
- SOCKET_READ_SIZE
Public Class Methods
new(options={})
click to toggle source
# File lib/ferris/rtm.rb, line 31 def initialize options={} @id = 0 @jobs = [] @stopped = false @callbacks = Hash.new { |h,k| h[k] = [] } @q = Queue.new @qlock = Mutex.new @token = options.fetch :token @api_url = options.fetch :api_url, 'https://slack.com/api' @logger = options.fetch :logger, Slog.new @wss_uri = construct_wss_uri @token, @api_url log.trace event: 'RTM client initialized', wss_uri: @wss_uri.to_s end
Public Instance Methods
go()
click to toggle source
# File lib/ferris/rtm.rb, line 66 def go log.trace event: 'connecting' socket, driver = connect log.debug event: 'connected' @jobs << go_read_input(socket, driver) @jobs << go_write_output(socket, driver) @jobs end
join()
click to toggle source
# File lib/ferris/rtm.rb, line 78 def join ; @jobs.map(&:join) end
kill()
click to toggle source
# File lib/ferris/rtm.rb, line 76 def kill ; @jobs.map(&:kill) end
on(event, &block)
click to toggle source
# File lib/ferris/rtm.rb, line 46 def on event, &block unless [ :open, :close, :error, :message ].include? event log.fatal event: 'invalid event', on_event: event raise ArgumentError end log.debug event: 'adding callback', on_event: event @callbacks[event] << block end
send(type, message={})
click to toggle source
# File lib/ferris/rtm.rb, line 57 def send type, message={} log.debug event: 'sending message', message: message message[:id] ||= next_id message[:type] = type enqueue message nil end
Private Instance Methods
connect()
click to toggle source
# File lib/ferris/rtm.rb, line 117 def connect tcp_socket = TCPSocket.new @wss_uri.host, HTTPS_PORT ssl_socket = OpenSSL::SSL::SSLSocket.new tcp_socket ssl_socket.connect writer = WebSocketWriter.new @wss_uri.to_s, ssl_socket driver = WebSocket::Driver.client writer driver.on :open do |_| log.trace event: 'driver open' @callbacks[:open].map(&:call) end driver.on :close do |_| log.trace event: 'driver close' @callbacks[:close].map(&:call) end driver.on :error do |_| log.trace event: 'driver error' @callbacks[:error].map(&:call) end driver.on :message do |event| log.trace event: 'driver message', message: event data = JSON.parse event.data @callbacks[:message].map { |c| c.call data } end driver.start [ ssl_socket, driver ] end
construct_wss_uri(token, api_url)
click to toggle source
# File lib/ferris/rtm.rb, line 87 def construct_wss_uri token, api_url uri = URI File.join(api_url, 'rtm.start') req = Net::HTTP.post_form uri, token: token bod = JSON.parse req.body, symbolize_names: true URI bod[:url] rescue x = { event: 'could not construct WSS URI' } x[:error] = bod[:error] if bod && bod[:error] log.fatal x raise RuntimeError end
enqueue(message)
click to toggle source
# File lib/ferris/rtm.rb, line 106 def enqueue message @qlock.synchronize { @q << message } end
full_dequeue(q=[])
click to toggle source
# File lib/ferris/rtm.rb, line 111 def full_dequeue q=[] nq = @qlock.synchronize { q << @q.shift until @q.empty? ; q } nq end
go_read_input(socket, driver)
click to toggle source
# File lib/ferris/rtm.rb, line 151 def go_read_input socket, driver Thread.new do loop do log.trace event: 'reading socket' data = socket.readpartial SOCKET_READ_SIZE log.debug event: 'read socket', data_size: data.size next if data.nil? || data.empty? driver.parse data end end end
go_write_output(socket, driver, delay=0.1)
click to toggle source
# File lib/ferris/rtm.rb, line 164 def go_write_output socket, driver, delay=0.1 Thread.new do loop do q = full_dequeue q.each do |m| sent = driver.text JSON.generate(m) unless sent log.fatal event: 'could not send', message: m raise RuntimeError end end sleep delay if q.empty? end end end
log()
click to toggle source
# File lib/ferris/rtm.rb, line 84 def log ; @logger end
next_id()
click to toggle source
# File lib/ferris/rtm.rb, line 101 def next_id @qlock.synchronize { @id += 1 } end