4 "github.com/Kovensky/go-anidb/misc"
5 "github.com/Kovensky/go-anidb/udp"
6 "github.com/Kovensky/go-fscache"
11 func (a *MyListAnime) setCachedTS(ts time.Time) {
15 func (a *MyListAnime) IsStale() bool {
20 return time.Now().Sub(a.Cached) > MyListCacheDuration
23 var _ cacheable = &MyListAnime{}
25 func (uid UID) MyListAnime(aid AID) *MyListAnime {
27 if CacheGet(&a, "mylist-anime", uid, aid) == nil {
33 func (adb *AniDB) MyListAnime(aid AID) <-chan *MyListAnime {
34 ch := make(chan *MyListAnime, 1)
43 user := <-adb.GetCurrentUser()
44 if user == nil || user.UID < 1 {
49 key := []fscache.CacheKey{"mylist-anime", user.UID, aid}
51 ic := make(chan notification, 1)
52 go func() { ch <- (<-ic).(*MyListAnime); close(ch) }()
53 if intentMap.Intent(ic, key...) {
57 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
58 intentMap.NotifyClose((*MyListAnime)(nil), key...)
62 entry := user.UID.MyListAnime(aid)
64 intentMap.NotifyClose(entry, key...)
68 reply := <-adb.udp.SendRecv("MYLIST", paramMap{"aid": aid})
72 r := adb.parseMylistReply(reply) // caches
74 // we have only a single file added for this anime -- construct a fake 312 struct
75 entry = &MyListAnime{AID: aid}
77 ep := <-adb.EpisodeByID(r.EID)
78 list := misc.EpisodeToList(&ep.Episode)
80 switch r.MyListState {
81 case MyListStateUnknown:
82 entry.UnknownState = list
87 case MyListStateDeleted:
91 if !r.DateWatched.IsZero() {
92 entry.WatchedEpisodes = list
95 entry.EpisodesPerGroup = map[GID]misc.EpisodeList{
99 entry = adb.parseMylistAnime(reply)
102 Cache.SetInvalid(key...)
105 CacheSet(entry, key...)
106 intentMap.NotifyClose(entry, key...)
111 func (adb *AniDB) UserMyListAnime(uid UID, aid AID) <-chan *MyListAnime {
112 key := []fscache.CacheKey{"mylist-anime", uid, aid}
113 ch := make(chan *MyListAnime, 1)
115 if uid < 1 || aid < 1 {
121 ic := make(chan notification, 1)
122 go func() { ch <- (<-ic).(*MyListAnime); close(ch) }()
123 if intentMap.Intent(ic, key...) {
127 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
128 intentMap.NotifyClose((*MyListAnime)(nil), key...)
132 entry := uid.MyListAnime(aid)
133 if !entry.IsStale() {
134 intentMap.NotifyClose(entry, key...)
139 user := <-adb.GetCurrentUser()
141 if user.UID != uid { // we can't query other users' lists from API
142 intentMap.NotifyClose(entry, key...)
146 intentMap.NotifyClose(<-adb.MyListAnime(aid), key...)
151 func (adb *AniDB) parseMylistAnime(reply udpapi.APIReply) *MyListAnime {
152 if reply.Code() != 312 {
156 parts := strings.Split(reply.Lines()[1], "|")
158 // Everything from index 7 on is pairs of group name on odd positions and episode list on even
159 var groupParts []string
161 groupParts = parts[7:]
164 groupMap := make(GroupEpisodes, len(groupParts)/2)
166 for i := 0; i+1 < len(groupParts); i += 2 {
167 g := <-adb.GroupByName(groupParts[i])
172 groupMap[g.GID] = misc.ParseEpisodeList(groupParts[i+1])
176 UnknownState: misc.ParseEpisodeList(parts[2]),
177 OnHDD: misc.ParseEpisodeList(parts[3]),
178 OnCD: misc.ParseEpisodeList(parts[4]),
179 Deleted: misc.ParseEpisodeList(parts[5]),
181 WatchedEpisodes: misc.ParseEpisodeList(parts[6]),
183 EpisodesPerGroup: groupMap,