mirror of
https://git.sr.ht/~ashkeel/strimertul
synced 2024-09-30 02:40:33 +00:00
115 lines
2.6 KiB
Go
115 lines
2.6 KiB
Go
|
package twitch
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"time"
|
||
|
|
||
|
"github.com/nicklaw5/helix/v2"
|
||
|
|
||
|
"git.sr.ht/~ashkeel/strimertul/database"
|
||
|
)
|
||
|
|
||
|
func GetConfig(db database.Database) (Config, error) {
|
||
|
var config Config
|
||
|
if err := db.GetJSON(ConfigKey, &config); err != nil {
|
||
|
return Config{}, fmt.Errorf("failed to get twitch config: %w", err)
|
||
|
}
|
||
|
return config, nil
|
||
|
}
|
||
|
|
||
|
type AuthResponse struct {
|
||
|
AccessToken string `json:"access_token"`
|
||
|
RefreshToken string `json:"refresh_token"`
|
||
|
ExpiresIn int `json:"expires_in"`
|
||
|
Scope []string `json:"scope"`
|
||
|
Time time.Time
|
||
|
}
|
||
|
|
||
|
func GetUserClient(db database.Database, forceRefresh bool) (*helix.Client, error) {
|
||
|
var authResp AuthResponse
|
||
|
if err := db.GetJSON(AuthKey, &authResp); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
// Handle token expiration
|
||
|
if forceRefresh || time.Now().After(authResp.Time.Add(time.Duration(authResp.ExpiresIn)*time.Second)) {
|
||
|
// Refresh tokens
|
||
|
api, err := GetHelixAPI(db)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
refreshed, err := api.RefreshUserAccessToken(authResp.RefreshToken)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
authResp.AccessToken = refreshed.Data.AccessToken
|
||
|
authResp.RefreshToken = refreshed.Data.RefreshToken
|
||
|
authResp.Time = time.Now().Add(time.Duration(refreshed.Data.ExpiresIn) * time.Second)
|
||
|
|
||
|
// Save new token pair
|
||
|
err = db.PutJSON(AuthKey, authResp)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
config, err := GetConfig(db)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return helix.NewClient(&helix.Options{
|
||
|
ClientID: config.APIClientID,
|
||
|
ClientSecret: config.APIClientSecret,
|
||
|
UserAccessToken: authResp.AccessToken,
|
||
|
})
|
||
|
}
|
||
|
|
||
|
func GetHelixAPI(db database.Database) (*helix.Client, error) {
|
||
|
config, err := GetConfig(db)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
baseurl, err := baseURL(db)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
redirectURI := getRedirectURI(baseurl)
|
||
|
|
||
|
// Create Twitch client
|
||
|
api, err := helix.NewClient(&helix.Options{
|
||
|
ClientID: config.APIClientID,
|
||
|
ClientSecret: config.APIClientSecret,
|
||
|
RedirectURI: redirectURI,
|
||
|
})
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
// Get access token
|
||
|
resp, err := api.RequestAppAccessToken([]string{"user:read:email"})
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
// Set the access token on the client
|
||
|
api.SetAppAccessToken(resp.Data.AccessToken)
|
||
|
|
||
|
return api, nil
|
||
|
}
|
||
|
|
||
|
func baseURL(db database.Database) (string, error) {
|
||
|
var severConfig struct {
|
||
|
Bind string `json:"bind"`
|
||
|
}
|
||
|
err := db.GetJSON("http/config", &severConfig)
|
||
|
return severConfig.Bind, err
|
||
|
}
|
||
|
|
||
|
func getRedirectURI(baseurl string) string {
|
||
|
return fmt.Sprintf("http://%s/twitch/callback", baseurl)
|
||
|
}
|