package ttv import ( "context" "encoding/json" "errors" "io" "net/http" "net/url" "github.com/adeithe/go-twitch/api" "zomo.dev/largehadroncollider/db" "zomo.dev/largehadroncollider/util" ) const TWITCH_AUTH_URL = "https://id.twitch.tv/oauth2/token" func initAuth(conf *util.Config, dbConn *db.DBConn) (*TwitchAuth, error) { ctx := context.Background() client := api.New(conf.ClientID) twitchAuth := &TwitchAuth{ctx, client} // run once synchronously then start looping in a thread twitchAuth.updateDetailsRefreshTokens(conf, dbConn) go twitchAuth.loopUpdateDetailsRefreshTokens(conf, dbConn) return twitchAuth, nil } type TwitchAuth struct { Ctx context.Context Client *api.Client } type TwitchAuthRespOk struct { Code string `json:"code"` Scope string `json:"scope"` State string `json:"state"` } type TwitchAuthRespErr struct { Err string `json:"error"` ErrDesc string `json:"error_description"` State string `json:"state"` } type TwitchAuthTokenResp struct { AccessToken string `json:"access_token"` ExpiresIn int `json:"expires_in"` RefreshToken string `json:"refresh_token"` Scope []string `json:"scope"` TokenType string `json:"token_type"` } func (twitch *TwitchAuth) doAuth(formData url.Values) (TwitchAuthTokenResp, error) { resp, err := http.PostForm(TWITCH_AUTH_URL, formData) if err != nil { return TwitchAuthTokenResp{}, err } defer resp.Body.Close() bodyBytes, err := io.ReadAll(resp.Body) if err != nil { return TwitchAuthTokenResp{}, err } var authResp TwitchAuthTokenResp err = json.Unmarshal(bodyBytes, &authResp) if err != nil { return TwitchAuthTokenResp{}, err } return authResp, nil } func (twitch *TwitchAuth) DoAuth(conf *util.Config, code string) (TwitchAuthTokenResp, error) { formData := url.Values{ "client_id": {conf.ClientID}, "client_secret": {conf.ClientSecret}, "redirect_uri": {conf.RedirectURI}, "code": {code}, "grant_type": {"authorization_code"}, } return twitch.doAuth(formData) } func (twitch *TwitchAuth) DoRefresh(conf *util.Config, refreshToken string) (TwitchAuthTokenResp, error) { formData := url.Values{ "client_id": {conf.ClientID}, "client_secret": {conf.ClientSecret}, "refresh_token": {refreshToken}, "grant_type": {"refresh_token"}, } return twitch.doAuth(formData) } func (twitch *TwitchAuth) GetTokenUser(accessToken string) (api.User, error) { return getTokenUser(twitch.Ctx, twitch.Client, accessToken) } func getTokenUser(ctx context.Context, client *api.Client, accessToken string) (api.User, error) { users, err := client.Users.List().Do(ctx, api.WithBearerToken(accessToken)) if err != nil { return api.User{}, err } usersData := users.Data if len(usersData) <= 0 { return api.User{}, errors.New("user data returned an empty array") } // from twitch return usersData[0], nil }