working on botTokens

This commit is contained in:
bryce
2025-07-22 11:33:24 +12:00
parent b0be1f99c8
commit 963e829b7f
5 changed files with 89 additions and 9 deletions

View File

@@ -39,6 +39,7 @@ func StartOAuthServer(addr string) error {
http.HandleFunc("/", handleIndex)
http.HandleFunc("/callback", handleCallback)
http.HandleFunc("/refresh", handleRefresh)
log.Printf("OAuth server listening on %s", addr)
return http.ListenAndServe(addr, nil)
@@ -46,7 +47,7 @@ func StartOAuthServer(addr string) error {
func handleIndex(w http.ResponseWriter, r *http.Request) {
authURL := fmt.Sprintf(
"https://id.twitch.tv/oauth2/authorize?response_type=code&client_id=%s&redirect_uri=%s&scope=%s",
"https://id.twitch.tv/oauth2/authorize?response_type=code&client_id=%s&redirect_uri=%s&scope=%s&force_verify=true",
url.QueryEscape(clientID),
url.QueryEscape(redirectURI),
url.QueryEscape(strings.Join(scopes, " ")),
@@ -77,10 +78,26 @@ func handleCallback(w http.ResponseWriter, r *http.Request) {
}
jsonData, _ := json.MarshalIndent(token, "", " ")
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Type", "application/ijson")
w.Write(jsonData)
}
func handleRefresh(w http.ResponseWriter, r *http.Request) {
refresh := r.URL.Query().Get("refresh_token")
if refresh == "" {
http.Error(w, "Missing refresh_token parameter", http.StatusBadRequest)
return
}
tr, err := ExchangeRefreshToken(refresh)
if err != nil {
http.Error(w, "Refresh failed: "+err.Error(), http.StatusInternalServerError)
return
}
data, _ := json.MarshalIndent(tr, "", " ")
w.Header().Set("Content-Type", "application/json")
w.Write(data)
}
func exchangeCodeForToken(code string) (*TokenResponse, error) {
data := url.Values{}
data.Set("client_id", clientID)
@@ -110,3 +127,31 @@ func exchangeCodeForToken(code string) (*TokenResponse, error) {
return &tokenResp, nil
}
// refresh tokens programtically
func ExchangeRefreshToken(refreshToken string) (*TokenResponse, error) {
form := url.Values{}
form.Set("client_id", clientID)
form.Set("client_secret", clientSecret)
form.Set("grant_type", "refresh_token")
form.Set("refresh_token", refreshToken)
resp, err := http.Post(
"https://id.twitch.tv/oauth2/token",
"application/x-www-form-urlencoded",
strings.NewReader(form.Encode()),
)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("refresh failed: %s", resp.Status)
}
var tr TokenResponse
if err := json.NewDecoder(resp.Body).Decode(&tr); err != nil {
return nil, err
}
return &tr, nil
}

View File

@@ -5,10 +5,12 @@ import (
"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) {
@@ -29,6 +31,29 @@ func NewClient(clientID, clientSecret string) (*Client, error) {
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) {