mirror of
https://github.com/skidoodle/spotify-ws
synced 2025-10-09 05:22:43 +02:00
fix ws
This commit is contained in:
@@ -2,36 +2,39 @@ package websocket
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"spotify-ws/internal/spotify"
|
||||
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
// Poller is responsible for fetching data from the Spotify API periodically.
|
||||
type Poller struct {
|
||||
client *spotify.Client
|
||||
hub *Hub
|
||||
realtime bool
|
||||
lastState *spotify.CurrentlyPlaying
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// NewPoller creates a new Poller.
|
||||
func NewPoller(client *spotify.Client, hub *Hub) *Poller {
|
||||
func NewPoller(client *spotify.Client, hub *Hub, realtime bool) *Poller {
|
||||
return &Poller{
|
||||
client: client,
|
||||
hub: hub,
|
||||
client: client,
|
||||
hub: hub,
|
||||
realtime: realtime,
|
||||
}
|
||||
}
|
||||
|
||||
// Run starts the polling loop. It must be run in a separate goroutine.
|
||||
// Run starts the polling loop.
|
||||
func (p *Poller) Run(ctx context.Context) {
|
||||
slog.Info("poller started")
|
||||
defer slog.Info("poller stopped")
|
||||
|
||||
p.UpdateState(ctx)
|
||||
|
||||
ticker := time.NewTicker(3 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
@@ -61,38 +64,31 @@ func (p *Poller) UpdateState(ctx context.Context) {
|
||||
p.mu.Unlock()
|
||||
|
||||
if hasChanged {
|
||||
if !p.hub.realtime {
|
||||
if !p.realtime {
|
||||
trackName := "Nothing"
|
||||
if current.Item != nil {
|
||||
trackName = current.Item.Name
|
||||
}
|
||||
slog.Info("state changed, broadcasting update", "isPlaying", current.IsPlaying, "track", trackName)
|
||||
}
|
||||
p.hub.Broadcast(current)
|
||||
}
|
||||
}
|
||||
|
||||
// SendLastState sends the cached state to a single new client.
|
||||
func (p *Poller) SendLastState(ws *websocket.Conn) {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
payload := newPlaybackState(current, p.realtime)
|
||||
message, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
slog.Error("failed to marshal playback state", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
if p.lastState == nil {
|
||||
return
|
||||
}
|
||||
clientPayload := newPlaybackState(p.lastState, p.hub.realtime)
|
||||
if err := websocket.JSON.Send(ws, clientPayload); err != nil {
|
||||
slog.Warn("failed to send initial state to client", "error", err, "remoteAddr", ws.RemoteAddr())
|
||||
p.hub.broadcast <- message
|
||||
}
|
||||
}
|
||||
|
||||
// hasStateChanged performs a robust comparison between the new and old states.
|
||||
// This function must be called within a lock.
|
||||
func (p *Poller) hasStateChanged(current *spotify.CurrentlyPlaying) bool {
|
||||
if p.lastState == nil {
|
||||
return true
|
||||
}
|
||||
if p.hub.realtime && current.IsPlaying && current.Item != nil {
|
||||
if p.realtime && current.IsPlaying && current.Item != nil {
|
||||
return true
|
||||
}
|
||||
if p.lastState.IsPlaying != current.IsPlaying {
|
||||
|
||||
Reference in New Issue
Block a user