Class: Slack::RealTime::Client

Inherits:
Object
  • Object
show all
Includes:
Api::Message, Api::MessageId, Api::Ping, Api::Typing
Defined in:
lib/slack/real_time/client.rb

Defined Under Namespace

Classes: ClientAlreadyStartedError, ClientNotStartedError

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Api::Typing

#typing

Methods included from Api::Message

#message

Methods included from Api::Ping

#ping

Constructor Details

#initialize(options = {}) ⇒ Client

Returns a new instance of Client.



18
19
20
21
22
23
24
25
26
# File 'lib/slack/real_time/client.rb', line 18

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

Class Method Details

.configObject



69
70
71
# File 'lib/slack/real_time/client.rb', line 69

def config
  Config
end

.configureObject



65
66
67
# File 'lib/slack/real_time/client.rb', line 65

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

Instance Method Details

#keep_alive?Boolean

Ensure the server is running, and ping the remote server if no other messages were sent.

Returns:

  • (Boolean)


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/slack/real_time/client.rb', line 100

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

#on(type, &block) ⇒ Object



34
35
36
37
# File 'lib/slack/real_time/client.rb', line 34

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

#run_loopObject



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/slack/real_time/client.rb', line 74

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

#run_ping!Object

Check if the remote server is responsive, and if not, restart the connection.



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/slack/real_time/client.rb', line 119

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'
    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

#run_ping?Boolean

Returns:

  • (Boolean)


138
139
140
# File 'lib/slack/real_time/client.rb', line 138

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

#start!(&block) ⇒ Object

Start RealTime client and block until it disconnects.



40
41
42
43
44
# File 'lib/slack/real_time/client.rb', line 40

def start!(&block)
  @callback = block if block
  build_socket
  @socket.start_sync(self)
end

#start_async(&block) ⇒ Object

Start RealTime client and return immediately. The RealTime::Client will run in the background.



48
49
50
51
52
# File 'lib/slack/real_time/client.rb', line 48

def start_async(&block)
  @callback = block if block
  build_socket
  @socket.start_async(self)
end

#started?Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/slack/real_time/client.rb', line 60

def started?
  @socket&.connected?
end

#stop!Object



54
55
56
57
58
# File 'lib/slack/real_time/client.rb', line 54

def stop!
  raise ClientNotStartedError unless started?

  @socket&.disconnect!
end

#to_sObject



146
147
148
149
150
151
152
# File 'lib/slack/real_time/client.rb', line 146

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

#websocket_ping_timerObject



142
143
144
# File 'lib/slack/real_time/client.rb', line 142

def websocket_ping_timer
  websocket_ping / 2
end