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, 2)
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 entry.EpisodesWithState = MyListStateMap{
84 if !r.DateWatched.IsZero() {
85 entry.WatchedEpisodes = list
88 entry.EpisodesPerGroup = GroupEpisodes{
92 entry = adb.parseMylistAnime(reply)
95 Cache.SetInvalid(key...)
98 CacheSet(entry, key...)
99 intentMap.NotifyClose(entry, key...)
104 func (adb *AniDB) UserMyListAnime(uid UID, aid AID) <-chan *MyListAnime {
105 key := []fscache.CacheKey{"mylist-anime", uid, aid}
106 ch := make(chan *MyListAnime, 1)
108 if uid < 1 || aid < 1 {
114 ic := make(chan notification, 1)
115 go func() { ch <- (<-ic).(*MyListAnime); close(ch) }()
116 if intentMap.Intent(ic, key...) {
120 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
121 intentMap.NotifyClose((*MyListAnime)(nil), key...)
125 entry := uid.MyListAnime(aid)
126 if !entry.IsStale() {
127 intentMap.NotifyClose(entry, key...)
132 user := <-adb.GetCurrentUser()
134 if user.UID != uid { // we can't query other users' lists from API
135 intentMap.NotifyClose(entry, key...)
139 intentMap.NotifyClose(<-adb.MyListAnime(aid), key...)
144 func (adb *AniDB) parseMylistAnime(reply udpapi.APIReply) *MyListAnime {
145 if reply.Code() != 312 {
149 parts := strings.Split(reply.Lines()[1], "|")
151 // Everything from index 7 on is pairs of group name on odd positions and episode list on even
152 var groupParts []string
154 groupParts = parts[7:]
157 groupMap := make(GroupEpisodes, len(groupParts)/2)
159 for i := 0; i+1 < len(groupParts); i += 2 {
160 g := <-adb.GroupByName(groupParts[i])
165 groupMap[g.GID] = misc.ParseEpisodeList(groupParts[i+1])
169 EpisodesWithState: MyListStateMap{
170 MyListStateUnknown: misc.ParseEpisodeList(parts[2]),
171 MyListStateHDD: misc.ParseEpisodeList(parts[3]),
172 MyListStateCD: misc.ParseEpisodeList(parts[4]),
173 MyListStateDeleted: misc.ParseEpisodeList(parts[5]),
176 WatchedEpisodes: misc.ParseEpisodeList(parts[6]),
178 EpisodesPerGroup: groupMap,