我如何写入 Slack 的套接字模式 websocket 端点以使用 Ruby 发送聊天消息?

What do I write to Slack's Socket-Mode websocket endpoint to send a chat message using Ruby?

我正在尝试使用 Ruby 为我的团队编写一个简单的 Slack 聊天机器人。这有点粗糙,因为 Slack 没有对 Ruby 的官方支持。尽管如此,我已经能够使用我编写的这段代码打开一个 websocket 并收听 Slack 事件:

# 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

文档让我相信我可以将 JSON 写入此 connection 例如

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
})

但我还没弄清楚 JSON 需要采用什么形式。

我也 运行 参与其中,并试图确定为什么文档没有提供明确的答案。看来您实际上并没有通过 websockets 发送回请求,而是仅使用 websockets 来接受请求。

这意味着您将使用类似 webAPI 的东西来执行响应操作,您可以在 PythonSDK with websockets example provided by Slack.

中看到这种模式

例如:

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"],
     )