4 "github.com/Kovensky/go-anidb/udp"
5 "github.com/Kovensky/go-fscache"
11 func (e *MyListEntry) setCachedTS(ts time.Time) {
15 func (e *MyListEntry) IsStale() bool {
20 max := MyListCacheDuration
21 if !e.DateWatched.IsZero() {
22 max = MyListWatchedCacheDuration
24 return time.Now().Sub(e.Cached) > max
27 var _ cacheable = &MyListEntry{}
29 func (lid LID) MyListEntry() *MyListEntry {
31 if CacheGet(&e, "lid", lid) == nil {
37 func (adb *AniDB) MyListByFile(f *File) <-chan *MyListEntry {
38 ch := make(chan *MyListEntry, 1)
47 user := <-adb.GetCurrentUser()
49 var entry *MyListEntry
51 if lid := f.LID[user.UID]; lid != 0 {
52 entry = <-adb.MyListByLID(lid)
55 entry = <-adb.MyListByFID(f.FID)
63 func (adb *AniDB) MyListByLID(lid LID) <-chan *MyListEntry {
64 key := []fscache.CacheKey{"mylist", lid}
65 ch := make(chan *MyListEntry, 1)
73 ic := make(chan notification, 1)
74 go func() { ch <- (<-ic).(*MyListEntry); close(ch) }()
75 if intentMap.Intent(ic, key...) {
79 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
80 intentMap.NotifyClose((*MyListEntry)(nil), key...)
84 entry := lid.MyListEntry()
86 intentMap.NotifyClose(entry, key...)
91 reply := <-adb.udp.SendRecv("MYLIST", paramMap{"lid": lid})
95 entry = adb.parseMylistReply(reply) // caches
97 panic("Multiple MYLIST entries when querying for single LID")
99 Cache.SetInvalid(key...)
102 intentMap.NotifyClose(entry, key...)
107 func (adb *AniDB) MyListByFID(fid FID) <-chan *MyListEntry {
108 ch := make(chan *MyListEntry, 1)
116 // This is an odd one: we lack enough data at first to create the cache key
118 user := <-adb.GetCurrentUser()
119 if user == nil || user.UID < 1 {
125 key := []fscache.CacheKey{"mylist", "by-fid", fid, user.UID}
127 ic := make(chan notification, 1)
128 go func() { ch <- (<-ic).(*MyListEntry); close(ch) }()
129 if intentMap.Intent(ic, key...) {
133 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
134 intentMap.NotifyClose((*MyListEntry)(nil), key...)
139 switch ts, err := Cache.Get(&lid, key...); {
140 case err == nil && time.Now().Sub(ts) < LIDCacheDuration:
141 intentMap.NotifyClose(<-adb.MyListByLID(lid), key...)
145 reply := <-adb.udp.SendRecv("MYLIST", paramMap{"fid": fid})
147 var entry *MyListEntry
149 switch reply.Code() {
151 entry = adb.parseMylistReply(reply) // caches
153 panic("Multiple MYLIST entries when querying for single FID")
155 Cache.SetInvalid(key...)
158 intentMap.NotifyClose(entry, key...)
163 func (adb *AniDB) parseMylistReply(reply udpapi.APIReply) *MyListEntry {
164 // 221: MYLIST ok, 310: MYLISTADD conflict (same return format as 221)
165 if reply.Code() != 221 && reply.Code() != 310 {
169 parts := strings.Split(reply.Lines()[1], "|")
170 ints := make([]int64, len(parts))
171 for i := range parts {
172 ints[i], _ = strconv.ParseInt(parts[i], 10, 64)
175 da := time.Unix(ints[5], 0)
179 dw := time.Unix(ints[7], 0)
195 State: FileState(ints[11]),
196 MyListState: MyListState(ints[6]),
203 user := <-adb.GetCurrentUser()
206 if f := e.FID.File(); f != nil {
207 f.LID[user.UID] = e.LID
208 Cache.Set(f, "fid", f.FID)
209 Cache.Chtime(f.Cached, "fid", f.FID)
212 mla := <-adb.MyListAnime(f.AID)
214 key := []fscache.CacheKey{"mylist-anime", user.UID, f.AID}
216 intentMap.Intent(nil, key...)
222 if mla.Cached.Before(now) {
223 el := mla.EpisodesWithState[e.MyListState]
224 el.Add(f.EpisodeNumber)
225 mla.EpisodesWithState[e.MyListState] = el
227 if e.DateWatched.IsZero() {
228 mla.WatchedEpisodes.Sub(f.EpisodeNumber)
230 mla.WatchedEpisodes.Add(f.EpisodeNumber)
233 eg := mla.EpisodesPerGroup[f.GID]
234 eg.Add(f.EpisodeNumber)
235 mla.EpisodesPerGroup[f.GID] = eg
237 if mla.Cached.IsZero() {
238 // as attractive as such an ancient mtime would be,
239 // few filesystems can represent it; just make it old enough
240 mla.Cached = now.Add(-2 * MyListCacheDuration)
243 Cache.Set(mla, key...)
244 Cache.Chtime(mla.Cached, key...)
247 // this unfortunately races if Intent returns true:
248 // only the first NotifyClose call actually notifies
249 go intentMap.NotifyClose(mla, key...)
252 CacheSet(e, "mylist", "by-fid", e.FID, user.UID)
255 CacheSet(e, "mylist", e.LID)