class SlackRTMReceiver::Session

Websocket client for the RTM session

Attributes

last_timestamp[R]
logger[R]
self_uid[R]
ts[R]
websocket[R]
ws[R]

Public Class Methods

new() click to toggle source
# File lib/slack-rtm-receiver/session.rb, line 17
def initialize
  @logger = SlackRTMReceiver.logger
  logger.debug 'Initializing Session...'
  reset_vars
end

Public Instance Methods

alive?() click to toggle source

True if RTM session is alive

# File lib/slack-rtm-receiver/session.rb, line 86
def alive?
  return true if ws && ts
  return false
end
close() click to toggle source

Close RTM session

# File lib/slack-rtm-receiver/session.rb, line 149
def close
  ws.close if ws
end
idle_time() click to toggle source

Idle for how long? @return [Float] seconds

# File lib/slack-rtm-receiver/session.rb, line 93
def idle_time
  return 0 unless alive?
  return Time.now - ts
end
ping(timeout = 5) click to toggle source

Send RTM ping @param timeout [Fixnum] timeout in seconds @return [Boolean] true if pinged

# File lib/slack-rtm-receiver/session.rb, line 101
def ping(timeout = 5)
  if @ping
    logger.debug 'RTM ping requested, but another was recently sent. Ignoring...'
    return false
  end
  event = send_event({type: 'ping', time: Time.now.to_f})
  return false unless event
  timer = EM::Timer.new(timeout) do
    logger.warn "RTM ping timed out: threshold #{timeout} sec"
    close
  end
  event[:em_timer] = timer
  @ping = event
  @stats[:pings_sent] ||= 0
  @stats[:pings_sent] += 1
  return true
end
ping_if_idle(sec = 10) click to toggle source

Ping if idle for more than set seconds @param sec [Fixnum] idle time in seconds @return [Boolean] true if pinged

# File lib/slack-rtm-receiver/session.rb, line 122
def ping_if_idle(sec = 10)
  return false if idle_time < sec
  ping
end
reset_vars() click to toggle source
# File lib/slack-rtm-receiver/session.rb, line 23
def reset_vars
  @self_uid = nil
  @websocket = nil
  @last_timestamp = nil
  @ping = nil
  @stats = {}
end
send_event(event) click to toggle source

Send RTM event @param event [Hash] RTM event; 'id' will be added automatically @return [Hash] the event that was sent

# File lib/slack-rtm-receiver/session.rb, line 76
def send_event(event)
  return nil unless alive?
  event[:id] = new_event_id
  ws.send(JSON.fast_generate(event))
  logger.info "Event sent with id: #{event[:id]} type: #{event[:type]}"
  logger.debug "Sent event: #{event}"
  return event
end
start(json) click to toggle source

Start RTM websocket session @param json [String] rtm.start response from Starter @return [Boolean] false if a session is already up

# File lib/slack-rtm-receiver/session.rb, line 34
def start(json)
  if ws
    logger.warn 'RTM session start requested, but already running. Ignoring...'
    return false
  end
  h = parse_rtm_start_res(json)
  @self_uid = h[:self_id]
  logger.info "I am Slack ID: #{self_uid}. Connecting to websocket...\n URL: #{h[:url]}"
  opts = {ping: 60}
  @websocket = Faye::WebSocket::Client.new(h[:url], nil, opts)

  ws.on :open do
    logger.debug 'Websocket opened'
    touch_ts
  end

  ws.on :message do |ws_event|
    touch_ts
    event = JSON.parse(ws_event.data, {symbolize_names: true})
    case event[:type]
    when 'hello'
      hello_handler(event)
    when 'pong'
      pong_handler(event)
    else
      run_event_handlers(event)
    end
    @stats[:events_received] ||= 0
    @stats[:events_received] += 1
  end

  ws.on :close do |ws_event|
    logger.warn 'RTM session closed'
    cleanup
  end
  
  return true
end
stats(opts = {}) click to toggle source

Return statistics @param opts [Hash] @return [Hash]

# File lib/slack-rtm-receiver/session.rb, line 130
def stats(opts = {})
  return nil if @stats.empty?
  secs = Time.now - @stats[:hello_time]
  secs = secs.to_i
  days = secs / 86400
  secs = secs % 86400
  hours = secs / 3600
  secs = secs % 3600
  mins = secs / 60
  secs = secs % 60
  if opts[:log]
    msg = "Statistics since #{@stats[:hello_time]} (#{days} days, #{hours} hrs, #{mins} mins, #{secs} secs)\n"
    msg << "#{@stats}"
    logger.info msg
  end
  return @stats
end

Private Instance Methods

cleanup() click to toggle source

Reset instance variables

# File lib/slack-rtm-receiver/session.rb, line 213
def cleanup
  stats({log: true})
  reset_vars
  logger.warn 'RTM session closed'
end
hello_handler(event) click to toggle source

Handle RTM hello

# File lib/slack-rtm-receiver/session.rb, line 171
def hello_handler(event)
  @stats[:hello_time] = Time.now
  logger.info 'Hello received, RTM session established'
end
new_event_id() click to toggle source

Get new RTM event ID

# File lib/slack-rtm-receiver/session.rb, line 202
def new_event_id
  @stats[:events_sent] ||= 0
  return @stats[:events_sent] += 1
end
parse_rtm_start_res(json) click to toggle source
# File lib/slack-rtm-receiver/session.rb, line 155
def parse_rtm_start_res(json)
  hash = JSON.parse(json, {symbolize_names: true})
  rtmstart_handler(hash)
  return {url: hash[:url], self_id: hash[:self][:id]}
end
pong_handler(event) click to toggle source

Handle RTM pong

# File lib/slack-rtm-receiver/session.rb, line 177
def pong_handler(event)
  @stats[:pongs_received] ||= 0
  @stats[:pongs_received] += 1
  if @ping.nil? || @ping[:id] != event[:reply_to]
    logger.warn "Unexpected RTM pong received\n Pong: #{event}"
    return
  end
  latency = Time.now.to_f - @ping[:time]
  logger.info "RTM pong received, ping latency: #{'%.5f' % latency} sec"
  @ping[:em_timer].cancel
  @ping = nil
  @stats[:last_ping_latency] =  latency
end
rtmstart_handler(hash) click to toggle source

Handle RTM start response

# File lib/slack-rtm-receiver/session.rb, line 162
def rtmstart_handler(hash)
  logger.info 'Processing RTM.start response...'
  handlers = SlackRTMReceiver.event_handlers
  handlers.each do |handler|
    handler.process_event(hash, self) if handler.type == :rtmstart
  end
end
run_event_handlers(event) click to toggle source

Run matching handlers

# File lib/slack-rtm-receiver/session.rb, line 192
def run_event_handlers(event)
  logger.debug "Received event: #{event}"
  return unless event[:type]
  handlers = SlackRTMReceiver.event_handlers
  handlers.each do |handler|
    handler.process_event(event, self) if handler.type == event[:type].to_sym
  end
end
touch_ts() click to toggle source

Update last timestamp

# File lib/slack-rtm-receiver/session.rb, line 208
def touch_ts
  @last_timestamp = Time.now
end