working state
This commit is contained in:
@@ -128,9 +128,20 @@ func (m *Manager) startWebSocketClient(messageCallback func(string)) error {
|
||||
|
||||
// Get EnableRoomCodeImage setting from config (defaults to false)
|
||||
enableRoomCodeImage := m.config.Viper().GetBool("jackbox.EnableRoomCodeImage")
|
||||
|
||||
|
||||
// Get configurable delays for room code broadcast
|
||||
imageDelay := time.Duration(m.config.Viper().GetInt("jackbox.RoomCodeImageDelay")) * time.Second
|
||||
plaintextDelay := time.Duration(m.config.Viper().GetInt("jackbox.RoomCodePlaintextDelay")) * time.Second
|
||||
if plaintextDelay == 0 {
|
||||
plaintextDelay = 29 * time.Second // default
|
||||
}
|
||||
m.log.Infof("Room code delays: imageDelay=%v, plaintextDelay=%v (raw config: image=%d, plaintext=%d)",
|
||||
imageDelay, plaintextDelay,
|
||||
m.config.Viper().GetInt("jackbox.RoomCodeImageDelay"),
|
||||
m.config.Viper().GetInt("jackbox.RoomCodePlaintextDelay"))
|
||||
|
||||
// Create WebSocket client (pass the API client for vote tracking)
|
||||
m.wsClient = NewWebSocketClient(apiURL, token, wrappedCallback, m.client, enableRoomCodeImage, m.log)
|
||||
m.wsClient = NewWebSocketClient(apiURL, token, wrappedCallback, m.client, enableRoomCodeImage, imageDelay, plaintextDelay, m.log)
|
||||
|
||||
// Connect to WebSocket
|
||||
if err := m.wsClient.Connect(); err != nil {
|
||||
|
||||
@@ -305,10 +305,10 @@ func GenerateRoomCodeImage(roomCode, gameTitle string) ([]byte, error) {
|
||||
}
|
||||
|
||||
// Animation parameters
|
||||
initialPauseFrames := 25 // Initial pause before animation starts (2.5 seconds at 10fps)
|
||||
fadeFrames := 10 // Number of frames for fade-in (1 second at 10fps)
|
||||
pauseFrames := 30 // Frames to pause between characters (3 seconds at 10fps)
|
||||
frameDelay := 10 // 10/100 second = 0.1s per frame (10 fps)
|
||||
initialPauseFrames := 1 // Initial pause before animation starts (2.5 seconds at 10fps)
|
||||
fadeFrames := 10 // Number of frames for fade-in (1 second at 10fps)
|
||||
pauseFrames := 30 // Frames to pause between characters (3 seconds at 10fps)
|
||||
frameDelay := 10 // 10/100 second = 0.1s per frame (10 fps)
|
||||
|
||||
// Helper function to draw a frame and convert to paletted
|
||||
drawFrame := func(charIndex int, fadeProgress float64) *image.Paletted {
|
||||
|
||||
@@ -24,8 +24,10 @@ type WebSocketClient struct {
|
||||
stopChan chan struct{}
|
||||
connected bool
|
||||
authenticated bool
|
||||
subscribedSession int
|
||||
enableRoomCodeImage bool // Whether to upload room code images to Kosmi
|
||||
subscribedSession int
|
||||
enableRoomCodeImage bool // Whether to upload room code images to Kosmi
|
||||
roomCodeImageDelay time.Duration // Delay before sending image announcement
|
||||
roomCodePlaintextDelay time.Duration // Delay before sending plaintext room code
|
||||
}
|
||||
|
||||
// WebSocket message types
|
||||
@@ -67,17 +69,19 @@ type GameAddedData struct {
|
||||
}
|
||||
|
||||
// NewWebSocketClient creates a new WebSocket client
|
||||
func NewWebSocketClient(apiURL, token string, messageCallback func(string), apiClient *Client, enableRoomCodeImage bool, log *logrus.Entry) *WebSocketClient {
|
||||
func NewWebSocketClient(apiURL, token string, messageCallback func(string), apiClient *Client, enableRoomCodeImage bool, roomCodeImageDelay, roomCodePlaintextDelay time.Duration, log *logrus.Entry) *WebSocketClient {
|
||||
return &WebSocketClient{
|
||||
apiURL: apiURL,
|
||||
token: token,
|
||||
messageCallback: messageCallback,
|
||||
apiClient: apiClient,
|
||||
enableRoomCodeImage: enableRoomCodeImage,
|
||||
log: log,
|
||||
reconnectDelay: 1 * time.Second,
|
||||
maxReconnect: 30 * time.Second,
|
||||
stopChan: make(chan struct{}),
|
||||
apiURL: apiURL,
|
||||
token: token,
|
||||
messageCallback: messageCallback,
|
||||
apiClient: apiClient,
|
||||
enableRoomCodeImage: enableRoomCodeImage,
|
||||
roomCodeImageDelay: roomCodeImageDelay,
|
||||
roomCodePlaintextDelay: roomCodePlaintextDelay,
|
||||
log: log,
|
||||
reconnectDelay: 1 * time.Second,
|
||||
maxReconnect: 30 * time.Second,
|
||||
stopChan: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +97,7 @@ func (c *WebSocketClient) Connect() error {
|
||||
} else if len(wsURL) > 8 && wsURL[:8] == "https://" {
|
||||
wsURL = "wss://" + wsURL[8:]
|
||||
}
|
||||
|
||||
|
||||
wsURL += "/api/sessions/live"
|
||||
|
||||
c.log.Infof("Connecting to WebSocket: %s", wsURL)
|
||||
@@ -169,7 +173,7 @@ func (c *WebSocketClient) Unsubscribe(sessionID int) error {
|
||||
if c.subscribedSession == sessionID {
|
||||
c.subscribedSession = 0
|
||||
}
|
||||
|
||||
|
||||
c.log.Infof("Unsubscribed from session %d", sessionID)
|
||||
return nil
|
||||
}
|
||||
@@ -327,7 +331,7 @@ func (c *WebSocketClient) handleGameAdded(data json.RawMessage) {
|
||||
// The message parameter should contain the full game announcement including any vote results
|
||||
func (c *WebSocketClient) broadcastWithRoomCodeImage(message, gameTitle, roomCode string) {
|
||||
c.log.Infof("🎨 Starting room code image generation and upload for: %s - %s", gameTitle, roomCode)
|
||||
|
||||
|
||||
// Generate room code image (animated GIF) with game title embedded
|
||||
c.log.Infof("📝 Step 1: Generating image...")
|
||||
imageData, err := GenerateRoomCodeImage(roomCode, gameTitle)
|
||||
@@ -360,6 +364,10 @@ func (c *WebSocketClient) broadcastWithRoomCodeImage(message, gameTitle, roomCod
|
||||
c.log.Infof("✅ Step 2 complete: Uploaded to %s", imageURL)
|
||||
|
||||
// Now that upload succeeded, send the full announcement with the message and URL
|
||||
if c.roomCodeImageDelay > 0 {
|
||||
c.log.Infof("⏳ Step 3: Waiting %v before broadcasting game announcement...", c.roomCodeImageDelay)
|
||||
time.Sleep(c.roomCodeImageDelay)
|
||||
}
|
||||
c.log.Infof("📢 Step 3: Broadcasting game announcement with URL...")
|
||||
fullMessage := fmt.Sprintf("%s %s", message, imageURL)
|
||||
if c.messageCallback != nil {
|
||||
@@ -369,18 +377,19 @@ func (c *WebSocketClient) broadcastWithRoomCodeImage(message, gameTitle, roomCod
|
||||
c.log.Error("❌ Step 3 failed: messageCallback is nil")
|
||||
}
|
||||
|
||||
// Send the plaintext room code after 19 seconds (to sync with animation completion)
|
||||
// Send the plaintext room code after configured delay (to sync with animation completion)
|
||||
// Capture callback and logger in closure
|
||||
callback := c.messageCallback
|
||||
logger := c.log
|
||||
plainRoomCode := roomCode // Capture room code for plain text message
|
||||
|
||||
c.log.Infof("⏰ Step 4: Starting 19-second timer goroutine for plaintext room code...")
|
||||
plaintextDelay := c.roomCodePlaintextDelay
|
||||
|
||||
c.log.Infof("⏰ Step 4: Starting %v timer goroutine for plaintext room code...", plaintextDelay)
|
||||
go func() {
|
||||
logger.Infof("⏰ [Goroutine started] Waiting 19 seconds before sending plaintext room code: %s", plainRoomCode)
|
||||
time.Sleep(19 * time.Second)
|
||||
logger.Infof("⏰ [19 seconds elapsed] Now sending plaintext room code...")
|
||||
|
||||
logger.Infof("⏰ [Goroutine started] Waiting %v before sending plaintext room code: %s", plaintextDelay, plainRoomCode)
|
||||
time.Sleep(plaintextDelay)
|
||||
logger.Infof("⏰ [%v elapsed] Now sending plaintext room code...", plaintextDelay)
|
||||
|
||||
if callback != nil {
|
||||
// Send just the room code in plaintext (for easy copy/paste)
|
||||
plaintextMessage := fmt.Sprintf("Room Code: %s", plainRoomCode)
|
||||
@@ -391,8 +400,8 @@ func (c *WebSocketClient) broadcastWithRoomCodeImage(message, gameTitle, roomCod
|
||||
logger.Error("❌ Message callback is nil when trying to send delayed room code")
|
||||
}
|
||||
}()
|
||||
|
||||
c.log.Infof("✅ Step 4 complete: Goroutine launched, will fire in 19 seconds")
|
||||
|
||||
c.log.Infof("✅ Step 4 complete: Goroutine launched, will fire in %v", plaintextDelay)
|
||||
}
|
||||
|
||||
// handleSessionEnded processes session.ended events
|
||||
@@ -409,14 +418,14 @@ func (c *WebSocketClient) AnnounceSessionEnd() {
|
||||
lastVote := c.apiClient.GetAndClearLastVoteResponse()
|
||||
if lastVote != nil {
|
||||
// Include final vote results
|
||||
message = fmt.Sprintf("🗳️ Final votes for %s: %d👍 %d👎 (Score: %d)\n🌙 Game Night has ended! Thanks for playing!",
|
||||
message = fmt.Sprintf("🗳️ Final votes for %s: %d👍 %d👎 (Score: %d)\n🌙 Game Night has ended! Thanks for playing!",
|
||||
lastVote.Game.Title,
|
||||
lastVote.Game.Upvotes, lastVote.Game.Downvotes, lastVote.Game.PopularityScore)
|
||||
} else {
|
||||
// No votes for final game
|
||||
message = "🌙 Game Night has ended! Thanks for playing!"
|
||||
}
|
||||
|
||||
|
||||
// Clear the active session
|
||||
c.apiClient.SetActiveSession(0)
|
||||
} else {
|
||||
@@ -486,10 +495,10 @@ func (c *WebSocketClient) handleDisconnect() {
|
||||
return
|
||||
case <-time.After(delay):
|
||||
c.log.Infof("Reconnecting... (delay: %v)", delay)
|
||||
|
||||
|
||||
if err := c.Connect(); err != nil {
|
||||
c.log.Errorf("Reconnection failed: %v", err)
|
||||
|
||||
|
||||
// Increase delay with exponential backoff
|
||||
delay *= 2
|
||||
if delay > c.maxReconnect {
|
||||
@@ -500,14 +509,14 @@ func (c *WebSocketClient) handleDisconnect() {
|
||||
|
||||
// Reconnected successfully
|
||||
c.log.Info("Reconnected successfully")
|
||||
|
||||
|
||||
// Re-subscribe if we were subscribed before
|
||||
if c.subscribedSession > 0 {
|
||||
if err := c.Subscribe(c.subscribedSession); err != nil {
|
||||
c.log.Errorf("Failed to re-subscribe: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -545,4 +554,3 @@ func (c *WebSocketClient) IsSubscribed() bool {
|
||||
defer c.mu.Unlock()
|
||||
return c.subscribedSession > 0
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user