Nonce errors shouldn't be fatal, sometimes weird stuff happens and retrying could fix it. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
121 lines
2.5 KiB
Go
121 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"git.ophivana.moe/cat/rpcfetch"
|
|
)
|
|
|
|
var (
|
|
pidS = strconv.Itoa(os.Getpid())
|
|
hostname string
|
|
launchTime = time.Now().Unix()
|
|
replCounter atomic.Uint64
|
|
)
|
|
|
|
var substitute = map[string]func(s *applyState) string{
|
|
"pid": func(_ *applyState) string {
|
|
return pidS
|
|
},
|
|
"hostname": func(_ *applyState) string {
|
|
return hostname
|
|
},
|
|
"1min": func(s *applyState) string {
|
|
s.populateLoadavg()
|
|
return s.loadavg[0]
|
|
},
|
|
"5min": func(s *applyState) string {
|
|
s.populateLoadavg()
|
|
return s.loadavg[1]
|
|
},
|
|
"15min": func(s *applyState) string {
|
|
s.populateLoadavg()
|
|
return s.loadavg[2]
|
|
},
|
|
"used": func(s *applyState) string {
|
|
s.populateMem()
|
|
return fmt.Sprintf("%.1f GiB", float64(s.mem[1]-s.mem[0])/(1<<20))
|
|
},
|
|
|
|
"total": func(s *applyState) string {
|
|
s.populateMem()
|
|
return fmt.Sprintf("%.1f GiB", float64(s.mem[1])/(1<<20))
|
|
},
|
|
}
|
|
|
|
type applyState struct {
|
|
loadavg *[3]string
|
|
mem *[2]int
|
|
}
|
|
|
|
func (s *applyState) replace(t string) string {
|
|
for k, f := range substitute {
|
|
t = strings.ReplaceAll(t, "%"+k, f(s))
|
|
go func() {
|
|
replCounter.Add(uint64(len(t)))
|
|
statusReplaces.SetText(strconv.Itoa(int(replCounter.Load())) + " bytes")
|
|
}()
|
|
}
|
|
return t
|
|
}
|
|
|
|
func apply() {
|
|
prof := conf.profile()
|
|
|
|
// open new client if ID changes
|
|
if d.ID() != prof.ID {
|
|
// close previous client
|
|
if err := d.Close(); err != nil {
|
|
log.Fatalf("error closing previous client: %s", err)
|
|
}
|
|
|
|
// open new client
|
|
d = rpcfetch.New(prof.ID)
|
|
}
|
|
|
|
confLock.RLock()
|
|
act := *prof.Activity
|
|
s := &applyState{}
|
|
|
|
act.State = s.replace(act.State)
|
|
act.Details = s.replace(act.Details)
|
|
act.Timestamps = &rpcfetch.ActivityTimestamps{Start: &launchTime}
|
|
act.Assets = &rpcfetch.ActivityAssets{
|
|
LargeImage: act.Assets.LargeImage,
|
|
LargeText: s.replace(act.Assets.LargeText),
|
|
SmallImage: act.Assets.SmallImage,
|
|
SmallText: s.replace(act.Assets.SmallText),
|
|
}
|
|
confLock.RUnlock()
|
|
|
|
if nonce, err := retry(&act, s); err != nil {
|
|
log.Fatalf("error setting activity: %s", err)
|
|
} else {
|
|
log.Printf("activity updated with nonce %s", nonce)
|
|
}
|
|
}
|
|
|
|
func retry(act *rpcfetch.Activity, s *applyState) (string, error) {
|
|
try:
|
|
nonce, err := d.SetActivity(act)
|
|
if errors.Is(err, rpcfetch.ErrAgain) || errors.Is(err, rpcfetch.ErrNonce) {
|
|
failureState(false)
|
|
log.Println("retrying in 5 seconds...")
|
|
time.Sleep(5 * time.Second)
|
|
goto try
|
|
}
|
|
failureState(true)
|
|
|
|
// update GUI
|
|
updateClientInfo(s)
|
|
|
|
return nonce, err
|
|
}
|