package main import ( "encoding/gob" "fmt" "log" "os" "path" "sync" "sync/atomic" "git.ophivana.moe/cat/rpcfetch" "github.com/google/uuid" ) var ( conf *config confLock = &sync.RWMutex{} defaultUUID = uuid.MustParse("7ec9eb89-5472-4392-a59b-531d7f8df442") ) type config struct { Size size `json:"size"` Current uuid.UUID `json:"current"` Profiles []preset `json:"profiles"` } type preset struct { UUID uuid.UUID `json:"uuid"` Title string `json:"title"` ID string `json:"id"` *rpcfetch.Activity } type size struct { Width float32 `json:"width"` // The number of units along the X axis. Height float32 `json:"height"` // The number of units along the Y axis. } type profLastCache struct { uuid uuid.UUID index int } var ( profLast atomic.Value ) func (c *config) profile() preset { confLock.RLock() defer confLock.RUnlock() cache := profLast.Load().(profLastCache) if c.Current == cache.uuid { return c.Profiles[cache.index] } for i, prof := range c.Profiles { if prof.UUID == c.Current { profLast.Store(profLastCache{ uuid: c.Current, index: i, }) return prof } } log.Fatalf( "configuration file corrupt: current profile %s does not exist", c.Current.String(), ) return preset{} } func save() { nf, err := os.CreateTemp(path.Dir(confPath), ".rpcfetch.conf.*") if err != nil { log.Fatalf("error creating temporary configuration file: %s", err) } confLock.RLock() if err = gob.NewEncoder(nf).Encode(conf); err != nil { fmt.Printf("error writing configuration file: %s\n", err) os.Exit(1) } confLock.RUnlock() if err = nf.Close(); err != nil { log.Fatalf("error closing temporary configuration file: %s", err) } if err = os.Rename(nf.Name(), confPath); err != nil { log.Fatalf("error renaming configuration file: %s", err) } log.Printf("saved configuration to %s", confPath) } // sample config so the program works out of the box var defaultConfig = config{ Size: size{ Width: 1 << 10, // will default to MinSize Height: 0, }, Current: defaultUUID, Profiles: []preset{ func() preset { p := copyTemplate() p.UUID = defaultUUID p.Title = "Default" return p }(), }, } func copyTemplate() preset { p := templateProfile p.UUID = uuid.New() act := *p.Activity ast := *act.Assets act.Assets = &ast p.Activity = &act return p } var templateProfile = preset{ ID: "1252927154480611351", Activity: &rpcfetch.Activity{ State: "%used / %total", Details: "%1min %5min %15min", Assets: &rpcfetch.ActivityAssets{ LargeImage: "yorha", LargeText: "%hostname", SmallImage: "flan", SmallText: "PID: %pid", }, }, }