package anidb import ( "github.com/EliasFleckenstein03/go-fscache" "strconv" "strings" "time" ) func (s *MyListStats) setCachedTS(t time.Time) { s.Cached = t } func (s *MyListStats) IsStale() bool { if s == nil || time.Now().Sub(s.Cached) > MyListCacheDuration { return true } return false } var _ cacheable = &MyListStats{} func (u *User) Stats() *MyListStats { if u == nil { return nil } var s MyListStats if CacheGet(&s, "mylist-stats", u.UID) == nil { return &s } return nil } func (adb *AniDB) MyListStats(user *User) <-chan *MyListStats { ch := make(chan *MyListStats, 1) if user == nil || user.UID < 1 { ch <- nil close(ch) return ch } key := []fscache.CacheKey{"mylist-stats", user.UID} ic := make(chan notification, 1) go func() { ch <- (<-ic).(*MyListStats) }() if intentMap.Intent(ic, key...) { return ch } stats := user.Stats() if !stats.IsStale() { defer intentMap.NotifyClose(stats, key...) return ch } go func() { if adb.User() == nil { r := adb.udp.ReAuth() if r.Code() >= 500 { intentMap.NotifyClose(stats, key...) return } } if user.UID != adb.User().UID { intentMap.NotifyClose(stats, key...) return } reply := <-adb.udp.SendRecv("MYLISTSTATS", nil) switch reply.Code() { case 222: parts := strings.Split(reply.Lines()[1], "|") ints := make([]int64, len(parts)) for i := range parts { ints[i], _ = strconv.ParseInt(parts[i], 10, 64) } stats = &MyListStats{ Anime: int(ints[0]), Episodes: int(ints[1]), Files: int(ints[2]), Filesize: ints[3] * 1024 * 1024, // it comes in MB AddedAnime: int(ints[4]), AddedEpisodes: int(ints[5]), AddedFiles: int(ints[6]), AddedGroups: int(ints[7]), Leech: float32(ints[8]) / 100, Glory: float32(ints[9]) / 100, ViewedPctDatabase: float32(ints[10]) / 100, MyListPctDatabase: float32(ints[11]) / 100, // ViewedPctMyList: float32(ints[12]) / 100, // we can calculate a more accurate value ViewedEpisodes: int(ints[13]), Votes: int(ints[14]), Reviews: int(ints[15]), ViewedTime: time.Duration(ints[16]) * time.Minute, } stats.ViewedPctMyList = float32(stats.ViewedEpisodes) / float32(stats.Episodes) if ac := AnimeCount(); ac > 0 { stats.AnimePctDatabase = float32(stats.Anime) / float32(ac) } CacheSet(stats, key...) } intentMap.NotifyClose(stats, key...) }() return ch }