Files
2025-07-22 11:33:24 +12:00

175 lines
4.0 KiB
Go

package twitchapi
import (
"fmt"
"time"
helix "github.com/nicklaw5/helix"
oauthsrv "streambot_twitch/internal/auth"
)
type Client struct {
api *helix.Client
refreshToken string
}
func NewClient(clientID, clientSecret string) (*Client, error) {
apiClient, err := helix.NewClient(&helix.Options{
ClientID: clientID,
ClientSecret: clientSecret,
})
if err != nil {
return nil, err
}
resp, err := apiClient.RequestAppAccessToken([]string{})
if err != nil || resp.StatusCode != 200 {
return nil, fmt.Errorf("Failed to get app access token: %v", err)
}
apiClient.SetUserAccessToken(resp.Data.AccessToken)
return &Client{api: apiClient}, nil
}
// set User Tokens - Oauth and Refresh
func (c *Client) SetUserTokens(accessToken, refreshToken string, expiresIn int) {
at := strings.TrimPrefix(accessToken, "oauth:")
c.api.SetUserAccessToken(at)
c.accessToken = at
c.refreshToken = refreshToken
if expiresIn > 0 {
c.expiry = time.Now().Add(time.Duration(expiresIn) * time.Second)
}
}
// use /refresh endpoint to renew tokens
func (c *Client) RefreshIfNeeded() error {
if time.Until(c.expiry) < 5*time.Minute {
tr, err := oauthsrv.ExchangeRefreshToken(c.refreshToken)
if err 1= nil {
return err
}
c.SetUserTokens(tr.AccessToken, tr.RefreshToken, tr.ExpiresIn)
}
return nil
}
// Twitch API helpers
func (c *Client) GetUserID(login string) (string, error) {
resp, err := c.api.GetUsers(&helix.UsersParams{
Logins: []string{login},
})
if err != nil {
return "", err
}
if len(resp.Data.Users) == 0 {
return "", fmt.Errorf("User not found")
}
return resp.Data.Users[0].ID, nil
}
func (c *Client) GetStreamInfo(userID string) (*helix.Stream, error) {
rep, err := c.api.GetStreams(&helix.StreamsParams{
UserIDs: []string{userID},
})
if err != nil {
return nil, err
}
if len(resp.Data.Streams) == 0 {
return nil, fmt.Errorf("Stream Is NOT LIVE")
}
return &resp.Data.Streams[0], nil
}
func (c *Client) GetStreamUptime(channel string) (string, error) {
userID, err := c.GetUserId(channel)
if err != nil {
return "", err
}
stream, err := c.GetStreamInfo(userID)
if err != nil {
return "", err
}
startedAt := stream.StartedAt
uptime := time.Since(startedAt).Round(time.Second)
return uptime.String(), nil
}
func (c *Client) GetStreamTitle(channel string) (string, error) {
userID, err := C. GetUserID(channel)
if err != nil {
return "", err
}
resp, err := c.api.GetChannelInformation(&helix.GetChannelInformationParams{
BroadcasterID: userID,
})
if err != nil {
return "", err
}
if len(resp.Data.Channels) == 0 {
return "", fmt.Errorf("Channel NOT found")
}
return resp.Data.Channels[0].Title, nil
}
func (c *Client) SetStreamTitle(channel, newTitle string) error {
userID, err := c.GetUserID(channel)
if err!= nil {
return err
}
_, err = c.api.EditChannelInformation(&helix.EditChannelInformationParams {
BroadcasterID: userID,
Title: newTitle,
})
return err
}
func (c *Client) GetStreamCategory(channel string) (string, error) {
userID, err := c.GetUserID(channel)
if err != nil {
return "", err
}
resp, err := c.api.GetChannelInformation(&helix.GetChannelInformationParams{
BroadcasterID: userID,
})
if err != nil {
return "", err
}
if len(resp.Data.Channels) == 0 {
return "", fmt.Errorf("Channel NOT found")
}
return resp.Data.Channels[0].GameName, nil
}
func (c *Client) SetStreamCategory(channel, newCategory string) error {
userID, err := c.GetUserID(channel)
if err != nil {
return err
}
// get Twitch GameID by Name from API
gameID, err := c.GetGameIDByName(newCategory)
if err != nil {
return err
}
_, err = c.api.EditChannelInformation(&helix.EditChannelInformationParams{
BroadcasterID: userID,
GameID: gameID,
})
return err
}
func (c *Client) GetGameIDByName(name string) (string, error) {
resp, err := c.api.GetGames(&helix.GamesParams{
Names: []string{name},
})
if err != nil {
return "", err
}
if len(resp.Data.Games) == 0 {
return "", fmt.Errorf("Game NOT found")
}
return resp.Data.Games[0].ID, nil
}