95 lines
2.7 KiB
Go
95 lines
2.7 KiB
Go
|
package controller
|
||
|
|
||
|
import (
|
||
|
"arimelody-web/model"
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
const TWITCH_API_BASE = "https://api.twitch.tv/helix/"
|
||
|
|
||
|
func TwitchSetup(app *model.AppState) error {
|
||
|
app.Twitch = &model.TwitchState{}
|
||
|
err := RefreshTwitchToken(app)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func RefreshTwitchToken(app *model.AppState) error {
|
||
|
if app.Twitch != nil && app.Twitch.Token != nil && time.Now().UTC().After(app.Twitch.Token.ExpiresAt) {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
requestUrl, _ := url.Parse("https://id.twitch.tv/oauth2/token")
|
||
|
req, _ := http.NewRequest(http.MethodPost, requestUrl.String(), bytes.NewBuffer([]byte(url.Values{
|
||
|
"client_id": []string{ app.Config.Twitch.ClientID },
|
||
|
"client_secret": []string{ app.Config.Twitch.Secret },
|
||
|
"grant_type": []string{ "client_credentials" },
|
||
|
}.Encode())))
|
||
|
|
||
|
res, err := http.DefaultClient.Do(req)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
type TwitchOAuthToken struct {
|
||
|
AccessToken string `json:"access_token"`
|
||
|
ExpiresIn int `json:"expires_in"`
|
||
|
TokenType string `json:"token_type"`
|
||
|
}
|
||
|
oauthResponse := TwitchOAuthToken{}
|
||
|
err = json.NewDecoder(res.Body).Decode(&oauthResponse)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
app.Twitch.Token = &model.TwitchOAuthToken{
|
||
|
AccessToken: oauthResponse.AccessToken,
|
||
|
ExpiresAt: time.Now().UTC().Add(time.Second * time.Duration(oauthResponse.ExpiresIn)).UTC(),
|
||
|
TokenType: oauthResponse.TokenType,
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
var lastStreamState *model.TwitchStreamInfo
|
||
|
var lastStreamStateAt time.Time
|
||
|
|
||
|
func GetTwitchStatus(app *model.AppState, broadcaster string) (*model.TwitchStreamInfo, error) {
|
||
|
if lastStreamState != nil && time.Now().UTC().Before(lastStreamStateAt.Add(time.Minute)) {
|
||
|
return lastStreamState, nil
|
||
|
}
|
||
|
|
||
|
requestUrl, _ := url.Parse(TWITCH_API_BASE + "streams")
|
||
|
requestUrl.RawQuery = url.Values{
|
||
|
"user_login": []string{ broadcaster },
|
||
|
}.Encode()
|
||
|
req, _ := http.NewRequest(http.MethodGet, requestUrl.String(), nil)
|
||
|
req.Header.Set("Client-Id", app.Config.Twitch.ClientID)
|
||
|
req.Header.Set("Authorization", "Bearer " + app.Twitch.Token.AccessToken)
|
||
|
|
||
|
res, err := http.DefaultClient.Do(req)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
type StreamsResponse struct {
|
||
|
Data []model.TwitchStreamInfo `json:"data"`
|
||
|
}
|
||
|
streamInfo := StreamsResponse{}
|
||
|
err = json.NewDecoder(res.Body).Decode(&streamInfo)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if len(streamInfo.Data) == 0 {
|
||
|
return nil, nil
|
||
|
}
|
||
|
|
||
|
lastStreamState = &streamInfo.Data[0]
|
||
|
lastStreamStateAt = time.Now().UTC()
|
||
|
return lastStreamState, nil
|
||
|
}
|