error:
2025-12-01T01:46:17Z INF Starting RocketChat client channel=#webhook server=wss://chat.redacted.xyz
2025-12-01T01:46:17Z INF Connecting to WebSocket url=wss://chat.redacted.xyz/websocket
2025-12-01T01:46:17Z INF Connected to RocketChat WebSocket
2025-12-01T01:46:17Z INF > Sent Connect
2025-12-01T01:46:17Z INF > Sent token
2025-12-01T01:46:17Z INF Found room channel=#webhook roomId=692cdf069e6f87cec12c8654
2025-12-01T01:46:17Z INF > Sent room subscribe message
2025-12-01T01:46:17Z ERR WebSocket connection lost error="websocket: close 1002 (protocol error)"
code:
func connectAndListen() error {
wsURL := strings.Replace(serverURL, "https://", "wss://", 1)
wsURL = strings.Replace(wsURL, "http://", "ws://", 1)
wsURL = wsURL + "/websocket"
log.Info().Str("url", wsURL).Msg("Connecting to WebSocket")
conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
if err != nil {
return fmt.Errorf("failed to connect to websocket: %w", err)
}
defer conn.Close()
log.Info().Msg("Connected to RocketChat WebSocket")
// Send connect message
if err := sendMessage(conn, Message{
Msg: "connect",
ID: "1",
Method: "connect",
Params: []interface{}{"1", false},
}); err != nil {
return fmt.Errorf("failed to send connect message: %w", err)
}
// Wait for connect response
//time.Sleep(2000 * time.Millisecond)
//time.Sleep(500 * time.Millisecond)
log.Info().Msg("> Sent Connect")
// Login with token
if err := sendMessage(conn, Message{
Msg: "method",
ID: "2",
Method: "login",
Params: []interface{}{map[string]string{"resume": token}},
}); err != nil {
return fmt.Errorf("failed to send login message: %w", err)
}
log.Info().Msg("> Sent token")
// Get room ID
roomID, err := getRoomID(conn, channel)
if err != nil {
return fmt.Errorf("failed to get room ID: %w", err)
}
log.Info().Str("roomId", roomID).Str("channel", channel).Msg("Found room")
// Subscribe to room messages
if err := sendMessage(conn, Message{
Msg: "sub",
ID: "3",
Method: "stream-room-messages",
Params: []interface{}{roomID, false},
}); err != nil {
return fmt.Errorf("failed to subscribe to room: %w", err)
}
log.Info().Msg("> Sent room subscribe message")
// Listen for messages
for {
_, message, err := conn.ReadMessage()
if err != nil {
log.Error().Err(err).Msg("WebSocket connection lost")
mu.Lock()
if reconnected {
mu.Unlock()
return fmt.Errorf("connection lost after reconnect attempt")
}
reconnected = true
mu.Unlock()
log.Info().Msg("Attempting to reconnect...")
time.Sleep(2 * time.Second)
// Close old connection
conn.Close()
// Try to reconnect
return connectAndListen()
}
var msg Message
if err := json.Unmarshal(message, &msg); err != nil {
log.Debug().Str("raw", string(message)).Msg("Could not parse message")
continue
}
// Handle ping/pong
if msg.Msg == "ping" {
if err := sendMessage(conn, Message{Msg: "pong"}); err != nil {
log.Error().Err(err).Msg("Failed to send pong")
}
continue
}
// Handle changed messages (new messages in room)
if msg.Msg == "changed" && len(msg.Fields) > 0 {
if args, ok := msg.Fields["args"].([]interface{}); ok && len(args) > 0 {
if msgData, ok := args[0].(map[string]interface{}); ok {
logRoomMessage(msgData)
}
}
}
}
}
func sendMessage(conn *websocket.Conn, msg Message) error {
data, err := json.Marshal(msg)
if err != nil {
return err
}
return conn.WriteMessage(websocket.TextMessage, data)
}