I am trying to write a simple Slack chatbot for my team using Ruby. It's a bit rough because Slack doesn't have official support for Ruby. Nevertheless, I've been able to open a websocket and listen to Slack events using this code I wrote:
# frozen_string_literal: true
require "async"
require "async/io/stream"
require "async/http/endpoint"
require "async/websocket/client"
require "excon"
require "json"
module Slack
class Client
Error = Class.new(StandardError)
AquisitionError = Class.new(Error)
ConnectionError = Class.new(Error)
CONNECTION_AQUISITION_ENDPOINT = "https://slack.com/api/apps.connections.open"
def initialize
@token = "my-app-token"
end
def connect
connection_info = Excon.post(CONNECTION_AQUISITION_ENDPOINT, headers: {
"Content-type": "application/x-www-form-urlencoded",
Authorization: "Bearer #{@token}",
})
result = JSON.parse(connection_info.body)
raise(AquisitionError) unless result["ok"] # better error later
websocket = Async::HTTP::Endpoint.parse(result["url"])
Async do |_task|
Async::WebSocket::Client.connect(websocket) do |connection|
payload = connection.read
raise(ConnectionError) unless connection_check(payload)
puts "Listening..."
handle(payload) while (payload = connection.read)
end
end
end
private
def connection_check(payload)
payload[:type] == "hello"
end
def handle(payload)
puts payload.inspect
end
end
end
The documentation leads me to believe that I can write JSON to this connection
e.g.
connection.write({
# JSON to send a message in Slack here
# Probably need to specify the channel somehow
# Probably need to specify if I'm using markdown
# Have no idea what the form should be
})
But I haven't been able to figure out what form that JSON needs to take.
I was also running into this and trying to determine why the docs do not provide a clear answer. It appears that you do not infact send requests back over websockets, and instead use websockets only to accept requests.
Which would mean that you would use something like the webAPI to perform responsive actions, you can see this pattern in the PythonSDK with websockets example provided by Slack.
eg:
if req.type == "events_api":
# Acknowledge the request, this ack is sent back over websockets
# the format is: { 'envelope_id': req['envelope_id'] }
response = SocketModeResponse(envelope_id=req.envelope_id)
client.send_socket_mode_response(response)
# Add a reaction to the message if it's a new message
# notice that this request uses the web_client here and not the socket one
if req.payload["event"]["type"] == "message" \
and req.payload["event"].get("subtype") is None:
client.web_client.reactions_add(
name="eyes",
channel=req.payload["event"]["channel"],
timestamp=req.payload["event"]["ts"],
)