Class: SlackSocketModeBot
- Inherits:
-
Object
- Object
- SlackSocketModeBot
- Defined in:
- lib/slack_socket_mode_bot.rb,
lib/slack_socket_mode_bot/version.rb,
lib/slack_socket_mode_bot/test_mode.rb,
sig/slack_socket_mode_bot.rbs
Defined Under Namespace
Classes: Error, SimpleWebSocket, TestMode
Constant Summary collapse
- API_BASE =
"https://slack.com/api/"- RETRY_AFTER_CAP =
Max seconds to sleep on a 429 Retry-After; #call may run in the event loop.
60- SELECT_TIMEOUT =
#run wakes at least this often so an empty watch set never blocks forever.
30- VERSION =
"0.9.3"
Instance Attribute Summary collapse
-
#test_mode ⇒ TestMode?
readonly
The offline test double when built with token: "test", otherwise nil.
Instance Method Summary collapse
-
#call(method, data, token: @token) ⇒ Object
: (String method, untyped data, ?token: String) -> untyped.
-
#initialize(token:, app_token: nil, num_of_connections: 4, debug: false, logger: nil) {|arg0| ... } ⇒ SlackSocketModeBot
constructor
: (token: String, ?app_token: String, ?num_of_connections: Integer, ?debug: boolean, ?logger: Logger) { (untyped) -> untyped } -> void.
-
#run ⇒ void
: -> bot.
-
#step ⇒ [ Array[IO], Array[IO] ]
: -> [Array[IO], Array[IO]].
-
#test_mode? ⇒ Boolean
: -> bool.
Constructor Details
#initialize(token:, app_token: nil, num_of_connections: 4, debug: false, logger: nil) {|arg0| ... } ⇒ SlackSocketModeBot
: (token: String, ?app_token: String, ?num_of_connections: Integer, ?debug: boolean, ?logger: Logger) { (untyped) -> untyped } -> void
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/slack_socket_mode_bot.rb', line 34 def initialize(token:, app_token: nil, num_of_connections: 4, debug: false, logger: nil, &callback) @token = token @app_token = app_token @conns = [] @debug = debug @logger = logger @events = {} @callback = callback @test_mode = nil if token == "test" # Offline test double; #call is stubbed and dispatch is driven without connecting. require_relative "slack_socket_mode_bot/test_mode" @test_mode = TestMode.new(self) end # app_token and the handler come as a pair, else the bot hangs or crashes on the first event. raise ArgumentError, "app_token is required on Socket Mode" if callback && !app_token raise ArgumentError, "block is required on Socket Mode" if app_token && !callback # No app token: Web API calls only, no Socket Mode connections. @num_of_connections = app_token ? num_of_connections : 0 replenish_connections unless test_mode? end |
Instance Attribute Details
#test_mode ⇒ TestMode? (readonly)
The offline test double when built with token: "test", otherwise nil.
57 58 59 |
# File 'lib/slack_socket_mode_bot.rb', line 57 def test_mode @test_mode end |
Instance Method Details
#call(method, data, token: @token) ⇒ Object
: (String method, untyped data, ?token: String) -> untyped
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/slack_socket_mode_bot.rb', line 65 def call(method, data, token: @token) return @test_mode.call(method, data) if @test_mode url = URI(API_BASE + method) body = JSON.generate(data) headers = { "Content-type" => "application/json; charset=utf-8", "Authorization" => "Bearer " + token, } retries = 0 begin res = Net::HTTP.post(url, body, headers) case res when Net::HTTPSuccess json = JSON.parse(res.body, symbolize_names: true) raise Error, json[:error] unless json[:ok] json when Net::HTTPTooManyRequests # Rejected, not processed: safe to retry after Retry-After seconds. raise Retry, Integer(res["retry-after"] || retries + 1) else # 5xx etc.: may already be processed, so don't retry; just don't crash. raise Error, "HTTP #{ res.code } #{ res. }" end rescue Socket::ResolutionError, Net::OpenTimeout # Never sent (DNS / connect failure): safe to retry. retries += 1 raise if retries >= 3 sleep 1 retry rescue Retry => e # Don't block the event loop on an absurdly long wait. retries += 1 raise Error, "rate limited (retry-after: #{ e.wait }s)" if retries >= 3 || e.wait > RETRY_AFTER_CAP sleep e.wait retry end end |
#run ⇒ void
This method returns an undefined value.
: -> bot
202 203 204 205 206 207 |
# File 'lib/slack_socket_mode_bot.rb', line 202 def run while true read_ios, write_ios = step IO.select(read_ios, write_ios, nil, SELECT_TIMEOUT) end end |
#step ⇒ [ Array[IO], Array[IO] ]
: -> [Array[IO], Array[IO]]
193 194 195 196 197 198 199 |
# File 'lib/slack_socket_mode_bot.rb', line 193 def step raise Error, "not supported in test mode" if @test_mode read_ios, write_ios = [], [] @conns.select! {|ws| ws.step(read_ios, write_ios) } replenish_connections return read_ios, write_ios end |
#test_mode? ⇒ Boolean
: -> bool
60 61 62 |
# File 'lib/slack_socket_mode_bot.rb', line 60 def test_mode? !!@test_mode end |