feat: add twitch live detection to streamer list

This commit is contained in:
2026-04-28 23:22:51 +02:00
parent 2f81173f1e
commit 01b044e305
7 changed files with 354 additions and 32 deletions
+53
View File
@@ -33,6 +33,17 @@ type Channel struct {
Login string
}
// StreamInfo describes whether a channel is live.
type StreamInfo struct {
Online bool
}
// PlaybackToken carries the Twitch playback token/signature pair for live HLS access.
type PlaybackToken struct {
Signature string
Value string
}
// StreamerStatus describes one row's resolution state in the UI.
type StreamerStatus string
@@ -47,6 +58,7 @@ type StreamerEntry struct {
ConfigLogin string
Login string
ChannelID string
Live bool
Status StreamerStatus
Error string
}
@@ -106,3 +118,44 @@ func (s *Service) ResolveStreamer(ctx context.Context, login string) (*Channel,
}
return &Channel{ID: data.User.ID, Login: resolvedLogin}, nil
}
// StreamInfo resolves whether the given channel ID is currently live.
func (s *Service) StreamInfo(ctx context.Context, channelID string) (*StreamInfo, error) {
var data struct {
User *struct {
Stream *struct {
ID string `json:"id"`
} `json:"stream"`
} `json:"user"`
}
if err := s.GQL.Do(ctx, gql.WithIsStreamLiveQuery(channelID), &data); err != nil {
return nil, err
}
if data.User == nil {
return nil, fmt.Errorf("stream info missing user for channel %s", channelID)
}
if data.User.Stream == nil {
return &StreamInfo{Online: false}, nil
}
return &StreamInfo{Online: true}, nil
}
// PlaybackAccessToken fetches the Twitch playback token needed to access a live stream.
func (s *Service) PlaybackAccessToken(ctx context.Context, login string) (*PlaybackToken, error) {
var data struct {
StreamPlaybackAccessToken *struct {
Signature string `json:"signature"`
Value string `json:"value"`
} `json:"streamPlaybackAccessToken"`
}
if err := s.GQL.Do(ctx, gql.PlaybackAccessToken(login), &data); err != nil {
return nil, err
}
if data.StreamPlaybackAccessToken == nil || data.StreamPlaybackAccessToken.Signature == "" || data.StreamPlaybackAccessToken.Value == "" {
return nil, fmt.Errorf("playback access token missing signature or value for %s", login)
}
return &PlaybackToken{
Signature: data.StreamPlaybackAccessToken.Signature,
Value: data.StreamPlaybackAccessToken.Value,
}, nil
}