Goondex/internal/config/keys.go

97 lines
2.2 KiB
Go

package config
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"sync"
)
// APIKeys holds external service credentials.
type APIKeys struct {
TPDBAPIKey string `json:"tpdb_api_key"`
AEAPIKey string `json:"ae_api_key"`
StashDBAPIKey string `json:"stashdb_api_key"`
StashDBEndpoint string `json:"stashdb_endpoint"`
}
const apiKeysFile = "config/api_keys.json"
var (
keysMu sync.RWMutex
cached *APIKeys
)
// GetAPIKeys returns the configured API keys, preferring the persisted file, falling back to environment variables.
func GetAPIKeys() APIKeys {
keysMu.RLock()
if cached != nil {
defer keysMu.RUnlock()
return *cached
}
keysMu.RUnlock()
keys := APIKeys{}
// Try file first.
if b, err := os.ReadFile(apiKeysFile); err == nil {
_ = json.Unmarshal(b, &keys)
}
// Fallback to env if fields are empty.
if keys.TPDBAPIKey == "" {
keys.TPDBAPIKey = os.Getenv("TPDB_API_KEY")
}
if keys.AEAPIKey == "" {
keys.AEAPIKey = os.Getenv("AE_API_KEY")
}
if keys.StashDBAPIKey == "" {
keys.StashDBAPIKey = os.Getenv("STASHDB_API_KEY")
}
if keys.StashDBEndpoint == "" {
keys.StashDBEndpoint = os.Getenv("STASHDB_ENDPOINT")
}
if keys.StashDBEndpoint == "" {
keys.StashDBEndpoint = "https://stashdb.org/graphql"
}
keysMu.Lock()
cached = &keys
keysMu.Unlock()
return keys
}
// SaveAPIKeys persists API keys to disk (config/api_keys.json) and updates cache.
func SaveAPIKeys(keys APIKeys) error {
keysMu.Lock()
defer keysMu.Unlock()
// Normalize whitespace.
keys.TPDBAPIKey = strings.TrimSpace(keys.TPDBAPIKey)
keys.AEAPIKey = strings.TrimSpace(keys.AEAPIKey)
keys.StashDBAPIKey = strings.TrimSpace(keys.StashDBAPIKey)
keys.StashDBEndpoint = strings.TrimSpace(keys.StashDBEndpoint)
if keys.StashDBEndpoint == "" {
keys.StashDBEndpoint = "https://stashdb.org/graphql"
}
if err := os.MkdirAll(filepath.Dir(apiKeysFile), 0o755); err != nil {
return fmt.Errorf("create config dir: %w", err)
}
data, err := json.MarshalIndent(keys, "", " ")
if err != nil {
return fmt.Errorf("marshal keys: %w", err)
}
if err := os.WriteFile(apiKeysFile, data, 0o600); err != nil {
return fmt.Errorf("write keys file: %w", err)
}
cached = &keys
return nil
}