home to your local SPACEGIRL 馃挮 arimelody.space
at dev 94 lines 2.7 kB view raw
1package controller 2 3import ( 4 "arimelody-web/model" 5 "bytes" 6 "encoding/json" 7 "net/http" 8 "net/url" 9 "time" 10) 11 12const TWITCH_API_BASE = "https://api.twitch.tv/helix/" 13 14func TwitchSetup(app *model.AppState) error { 15 app.Twitch = &model.TwitchState{} 16 err := RefreshTwitchToken(app) 17 return err 18} 19 20func RefreshTwitchToken(app *model.AppState) error { 21 if app.Twitch != nil && app.Twitch.Token != nil && time.Now().UTC().After(app.Twitch.Token.ExpiresAt) { 22 return nil 23 } 24 25 requestUrl, _ := url.Parse("https://id.twitch.tv/oauth2/token") 26 req, _ := http.NewRequest(http.MethodPost, requestUrl.String(), bytes.NewBuffer([]byte(url.Values{ 27 "client_id": []string{ app.Config.Twitch.ClientID }, 28 "client_secret": []string{ app.Config.Twitch.Secret }, 29 "grant_type": []string{ "client_credentials" }, 30 }.Encode()))) 31 32 res, err := http.DefaultClient.Do(req) 33 if err != nil { 34 return err 35 } 36 37 type TwitchOAuthToken struct { 38 AccessToken string `json:"access_token"` 39 ExpiresIn int `json:"expires_in"` 40 TokenType string `json:"token_type"` 41 } 42 oauthResponse := TwitchOAuthToken{} 43 err = json.NewDecoder(res.Body).Decode(&oauthResponse) 44 if err != nil { 45 return err 46 } 47 48 app.Twitch.Token = &model.TwitchOAuthToken{ 49 AccessToken: oauthResponse.AccessToken, 50 ExpiresAt: time.Now().UTC().Add(time.Second * time.Duration(oauthResponse.ExpiresIn)).UTC(), 51 TokenType: oauthResponse.TokenType, 52 } 53 54 return nil 55} 56 57var lastStreamState *model.TwitchStreamInfo 58var lastStreamStateAt time.Time 59 60func GetTwitchStatus(app *model.AppState, broadcaster string) (*model.TwitchStreamInfo, error) { 61 if lastStreamState != nil && time.Now().UTC().Before(lastStreamStateAt.Add(time.Minute)) { 62 return lastStreamState, nil 63 } 64 65 requestUrl, _ := url.Parse(TWITCH_API_BASE + "streams") 66 requestUrl.RawQuery = url.Values{ 67 "user_login": []string{ broadcaster }, 68 }.Encode() 69 req, _ := http.NewRequest(http.MethodGet, requestUrl.String(), nil) 70 req.Header.Set("Client-Id", app.Config.Twitch.ClientID) 71 req.Header.Set("Authorization", "Bearer " + app.Twitch.Token.AccessToken) 72 73 res, err := http.DefaultClient.Do(req) 74 if err != nil { 75 return nil, err 76 } 77 78 type StreamsResponse struct { 79 Data []model.TwitchStreamInfo `json:"data"` 80 } 81 streamInfo := StreamsResponse{} 82 err = json.NewDecoder(res.Body).Decode(&streamInfo) 83 if err != nil { 84 return nil, err 85 } 86 87 if len(streamInfo.Data) == 0 { 88 return nil, nil 89 } 90 91 lastStreamState = &streamInfo.Data[0] 92 lastStreamStateAt = time.Now().UTC() 93 return lastStreamState, nil 94}