139 lines
4.4 KiB
Go
139 lines
4.4 KiB
Go
package websocket
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// INT-014: Standardized WebSocket message format
|
|
|
|
// MessageType represents the type of WebSocket message
|
|
type MessageType string
|
|
|
|
const (
|
|
// Connection messages
|
|
MessageTypePing MessageType = "ping"
|
|
MessageTypePong MessageType = "pong"
|
|
MessageTypeError MessageType = "error"
|
|
|
|
// Subscription messages
|
|
MessageTypeSubscribe MessageType = "subscribe"
|
|
MessageTypeUnsubscribe MessageType = "unsubscribe"
|
|
MessageTypeSubscribed MessageType = "subscribed"
|
|
MessageTypeUnsubscribed MessageType = "unsubscribed"
|
|
|
|
// Chat messages
|
|
MessageTypeChatMessage MessageType = "chat_message"
|
|
MessageTypeTyping MessageType = "typing"
|
|
MessageTypeReadReceipt MessageType = "read_receipt"
|
|
MessageTypeUserJoined MessageType = "user_joined"
|
|
MessageTypeUserLeft MessageType = "user_left"
|
|
MessageTypeConversationUpdated MessageType = "conversation_updated"
|
|
|
|
// Playback messages
|
|
MessageTypePlaybackState MessageType = "playback_state"
|
|
MessageTypePlaybackSync MessageType = "playback_sync"
|
|
MessageTypeAnalyticsUpdate MessageType = "analytics_update"
|
|
MessageTypeStatsUpdate MessageType = "stats_update"
|
|
|
|
// Notification messages
|
|
MessageTypeNotification MessageType = "notification"
|
|
)
|
|
|
|
// WebSocketMessage represents a standardized WebSocket message format
|
|
// INT-014: All WebSocket messages follow this structure
|
|
type WebSocketMessage struct {
|
|
// Message identification
|
|
ID string `json:"id,omitempty"` // Unique message ID (UUID)
|
|
Type string `json:"type"` // Message type (required)
|
|
Timestamp string `json:"timestamp"` // ISO 8601 timestamp (RFC3339)
|
|
|
|
// Message data
|
|
Data interface{} `json:"data,omitempty"` // Message payload (optional)
|
|
|
|
// Error information (for error messages)
|
|
Error *MessageError `json:"error,omitempty"` // Error details (for error type messages)
|
|
|
|
// Context information
|
|
RequestID string `json:"request_id,omitempty"` // Request ID for correlation
|
|
UserID string `json:"user_id,omitempty"` // User ID (if applicable)
|
|
TrackID string `json:"track_id,omitempty"` // Track ID (if applicable)
|
|
ConversationID string `json:"conversation_id,omitempty"` // Conversation ID (if applicable)
|
|
}
|
|
|
|
// MessageError represents error information in WebSocket messages
|
|
type MessageError struct {
|
|
Code int `json:"code"` // Error code
|
|
Message string `json:"message"` // Error message
|
|
Details map[string]interface{} `json:"details,omitempty"` // Additional error details
|
|
}
|
|
|
|
// NewWebSocketMessage creates a new WebSocket message with standardized format
|
|
func NewWebSocketMessage(msgType MessageType, data interface{}) *WebSocketMessage {
|
|
return &WebSocketMessage{
|
|
ID: uuid.New().String(),
|
|
Type: string(msgType),
|
|
Timestamp: time.Now().UTC().Format(time.RFC3339),
|
|
Data: data,
|
|
}
|
|
}
|
|
|
|
// NewErrorMessage creates a new error WebSocket message
|
|
func NewErrorMessage(code int, message string, details map[string]interface{}) *WebSocketMessage {
|
|
return &WebSocketMessage{
|
|
ID: uuid.New().String(),
|
|
Type: string(MessageTypeError),
|
|
Timestamp: time.Now().UTC().Format(time.RFC3339),
|
|
Error: &MessageError{
|
|
Code: code,
|
|
Message: message,
|
|
Details: details,
|
|
},
|
|
}
|
|
}
|
|
|
|
// WithRequestID sets the request ID for correlation
|
|
func (m *WebSocketMessage) WithRequestID(requestID string) *WebSocketMessage {
|
|
m.RequestID = requestID
|
|
return m
|
|
}
|
|
|
|
// WithUserID sets the user ID
|
|
func (m *WebSocketMessage) WithUserID(userID string) *WebSocketMessage {
|
|
m.UserID = userID
|
|
return m
|
|
}
|
|
|
|
// WithTrackID sets the track ID
|
|
func (m *WebSocketMessage) WithTrackID(trackID string) *WebSocketMessage {
|
|
m.TrackID = trackID
|
|
return m
|
|
}
|
|
|
|
// WithConversationID sets the conversation ID
|
|
func (m *WebSocketMessage) WithConversationID(conversationID string) *WebSocketMessage {
|
|
m.ConversationID = conversationID
|
|
return m
|
|
}
|
|
|
|
// ToJSON converts the message to JSON bytes
|
|
func (m *WebSocketMessage) ToJSON() ([]byte, error) {
|
|
return json.Marshal(m)
|
|
}
|
|
|
|
// ParseWebSocketMessage parses a JSON message into WebSocketMessage
|
|
func ParseWebSocketMessage(data []byte) (*WebSocketMessage, error) {
|
|
var msg WebSocketMessage
|
|
if err := json.Unmarshal(data, &msg); err != nil {
|
|
return nil, err
|
|
}
|
|
return &msg, nil
|
|
}
|
|
|
|
// IsValid checks if the message has required fields
|
|
func (m *WebSocketMessage) IsValid() bool {
|
|
return m.Type != "" && m.Timestamp != ""
|
|
}
|
|
|