package main import ( "encoding/json" "fmt" "log" "net/http" "os" "time" "github.com/hashicorp/golang-lru/v2/expirable" ) var ( pkApi = NewPluralKit() ) type PluralKitSwitch struct { Members []*PluralKitMember } type PluralKitSwitches struct { Members []string } type PluralKitMember struct { UUID string `json:"uuid"` Name string `json:"name"` } type PluralKit struct { Client http.Client Cache *expirable.LRU[string, *PluralKitMember] BaseURL string } func NewPluralKit() PluralKit { return PluralKit{ BaseURL: "https://api.pluralkit.me/v2", Client: http.Client{Timeout: time.Second * 30}, Cache: expirable.NewLRU[string, *PluralKitMember](20, nil, time.Hour), } } func (pk *PluralKit) GetMember(id string) (*PluralKitMember, error) { cached, ok := pk.Cache.Get(id) if ok { return cached, nil } resp, err := pk.Client.Get(fmt.Sprintf("%s/members/%s", pk.BaseURL, id)) if err != nil { return nil, fmt.Errorf("fetching pluralkit member %s failed: %w", id, err) } if resp.StatusCode != 200 { return nil, fmt.Errorf("pluralkit did not find member %s", id) } var member PluralKitMember err = json.NewDecoder(resp.Body).Decode(&member) if err != nil { return nil, fmt.Errorf("malformed json: %w", err) } pk.Cache.Add(id, &member) return &member, nil } func (pk *PluralKit) GetSwitch(systemID string, switchID string) (*PluralKitSwitch, error) { resp, err := pk.Client.Get(fmt.Sprintf("%s/systems/%s/switches/%s", pk.BaseURL, systemID, switchID)) if err != nil { return nil, fmt.Errorf("fetching pluralkit system %s switch %s failed: %w", systemID, switchID, err) } if resp.StatusCode != 200 { return nil, fmt.Errorf("pluralkit did not find system %s switch %s", systemID, switchID) } var sw PluralKitSwitch err = json.NewDecoder(resp.Body).Decode(&sw) if err != nil { return nil, fmt.Errorf("malformed json: %w", err) } for _, member := range sw.Members { pk.Cache.Add(member.UUID, member) } return &sw, nil } func (pk *PluralKit) GetSwitches(systemID string) (*PluralKitSwitches, error) { resp, err := pk.Client.Get(fmt.Sprintf("%s/systems/%s/switches", pk.BaseURL, systemID)) if err != nil { return nil, fmt.Errorf("fetching pluralkit system %s failed: %w", systemID, err) } if resp.StatusCode != 200 { return nil, fmt.Errorf("pluralkit did not find system %s", systemID) } var sw []PluralKitSwitches err = json.NewDecoder(resp.Body).Decode(&sw) if err != nil { return nil, fmt.Errorf("malformed json: %w", err) } return &sw[0], nil } func populateSwitches() { sysID := os.Getenv("PK_SYSTEM_ID") switches, err := pkApi.GetSwitches(sysID) if err != nil { log.Fatalln("failed to prepopulate switches.", err) } members := make([]*PluralKitMember, len(switches.Members)) for idx, id := range switches.Members { m, err := pkApi.GetMember(id) if err != nil { log.Fatalln("failed to get member.", err) } members[idx] = m } promCountSwitches(sysID, members) }