4 "github.com/Kovensky/go-anidb/http"
5 "github.com/Kovensky/go-anidb/udp"
6 "github.com/Kovensky/go-fscache"
12 var _ cacheable = &Group{}
14 func (g *Group) setCachedTS(ts time.Time) {
18 func (g *Group) IsStale() bool {
22 return time.Now().Sub(g.Cached) > GroupCacheDuration
25 // Unique Group IDentifier
28 func cacheGroup(g *Group) {
29 CacheSet(g.GID, "gid", "by-name", g.Name)
30 CacheSet(g.GID, "gid", "by-shortname", g.ShortName)
31 CacheSet(g, "gid", g.GID)
34 // Retrieves the Group from the cache.
35 func (gid GID) Group() *Group {
37 if CacheGet(&g, "gid", gid) == nil {
43 // Retrieves a Group by its GID. Uses the UDP API.
44 func (adb *AniDB) GroupByID(gid GID) <-chan *Group {
45 key := []fscache.CacheKey{"gid", gid}
46 ch := make(chan *Group, 1)
54 ic := make(chan notification, 1)
55 go func() { ch <- (<-ic).(*Group); close(ch) }()
56 if intentMap.Intent(ic, key...) {
60 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
61 intentMap.NotifyClose((*Group)(nil), key...)
67 intentMap.NotifyClose(g, key...)
72 reply := <-adb.udp.SendRecv("GROUP",
75 if reply.Error() == nil {
76 g = parseGroupReply(reply)
79 } else if reply.Code() == 350 {
80 Cache.SetInvalid(key...)
83 intentMap.NotifyClose(g, key...)
88 // Retrieves a Group by its name. Either full or short names are matched.
90 func (adb *AniDB) GroupByName(gname string) <-chan *Group {
91 key := []fscache.CacheKey{"gid", "by-name", gname}
92 altKey := []fscache.CacheKey{"gid", "by-shortname", gname}
93 ch := make(chan *Group, 1)
101 ic := make(chan notification, 1)
105 ch <- <-adb.GroupByID(gid)
109 if intentMap.Intent(ic, key...) {
113 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
114 intentMap.NotifyClose(GID(0), key...)
120 switch ts, err := Cache.Get(&gid, key...); {
121 case err == nil && time.Now().Sub(ts) < GroupCacheDuration:
122 intentMap.NotifyClose(gid, key...)
125 switch ts, err = Cache.Get(&gid, altKey...); {
126 case err == nil && time.Now().Sub(ts) < GroupCacheDuration:
127 intentMap.NotifyClose(gid, key...)
133 reply := <-adb.udp.SendRecv("GROUP",
134 paramMap{"gname": gname})
137 if reply.Error() == nil {
138 g = parseGroupReply(reply)
143 } else if reply.Code() == 350 {
144 Cache.SetInvalid(key...)
145 Cache.SetInvalid(altKey...)
148 intentMap.NotifyClose(gid, key...)
153 func parseGroupReply(reply udpapi.APIReply) *Group {
154 parts := strings.Split(reply.Lines()[1], "|")
155 ints := make([]int64, len(parts))
156 for i := range parts {
157 ints[i], _ = strconv.ParseInt(parts[i], 10, 32)
162 irc = "irc://" + parts[8] + "/" + parts[7][1:]
167 pic = httpapi.AniDBImageBaseURL + parts[10]
170 rellist := strings.Split(parts[16], "'")
171 relations := make(map[GID]GroupRelationType, len(rellist))
172 for _, rel := range rellist {
173 r := strings.Split(rel, ",")
177 gid, _ := strconv.ParseInt(r[0], 10, 32)
178 typ, _ := strconv.ParseInt(r[1], 10, 32)
180 relations[GID(gid)] = GroupRelationType(typ)
183 ft := time.Unix(ints[11], 0)
187 dt := time.Unix(ints[12], 0)
191 lr := time.Unix(ints[14], 0)
195 la := time.Unix(ints[15], 0)
217 Rating: float32(ints[1]) / 100,
218 VoteCount: int(ints[2]),
220 AnimeCount: int(ints[3]),
221 FileCount: int(ints[4]),
223 RelatedGroups: relations,