home to your local SPACEGIRL 馃挮
arimelody.space
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}