4 "github.com/Kovensky/go-anidb/udp"
5 "github.com/Kovensky/go-fscache"
14 func (adb *AniDB) GetCurrentUser() <-chan *User {
15 ch := make(chan *User, 1)
17 if adb.udp.credentials == nil {
23 return adb.GetUserByName(decrypt(adb.udp.credentials.username))
26 // This is an (almost) entirely local representation.
27 func (adb *AniDB) GetUserByID(uid UID) <-chan *User {
28 key := []fscache.CacheKey{"user", uid}
29 ch := make(chan *User, 1)
37 ic := make(chan notification, 1)
38 go func() { ch <- (<-ic).(*User); close(ch) }()
39 if intentMap.Intent(ic, key...) {
43 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
44 intentMap.NotifyClose((*User)(nil), key...)
50 if CacheGet(&user, key...) == nil {
51 intentMap.NotifyClose(user, key...)
54 <-adb.GetUserName(uid)
56 CacheGet(&user, key...)
57 intentMap.NotifyClose(user)
62 func (adb *AniDB) GetUserByName(username string) <-chan *User {
63 ch := make(chan *User, 1)
72 ch <- <-adb.GetUserByID(<-adb.GetUserUID(username))
78 func (adb *AniDB) GetUserUID(username string) <-chan UID {
79 key := []fscache.CacheKey{"user", "by-name", username}
80 ch := make(chan UID, 1)
88 ic := make(chan notification, 1)
89 go func() { ch <- (<-ic).(UID); close(ch) }()
90 if intentMap.Intent(ic, key...) {
94 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
95 intentMap.NotifyClose((UID)(0), key...)
100 switch ts, err := Cache.Get(&uid, key...); {
101 case err == nil && time.Now().Sub(ts) < UIDCacheDuration:
102 intentMap.NotifyClose(uid, key...)
107 reply := <-adb.udp.SendRecv("USER",
108 paramMap{"user": username})
110 switch reply.Code() {
112 uid, _ = parseUserReply(reply) // caches
114 Cache.SetInvalid(key...)
117 intentMap.NotifyClose(uid, key...)
122 func (adb *AniDB) GetUserName(uid UID) <-chan string {
123 key := []fscache.CacheKey{"user", "by-uid", uid}
124 ch := make(chan string, 1)
132 ic := make(chan notification, 1)
133 go func() { ch <- (<-ic).(string); close(ch) }()
134 if intentMap.Intent(ic, key...) {
138 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
139 intentMap.NotifyClose("", key...)
144 switch ts, err := Cache.Get(&name, key...); {
145 case err == nil && time.Now().Sub(ts) < UIDCacheDuration:
146 intentMap.NotifyClose(name, key...)
151 reply := <-adb.udp.SendRecv("USER",
152 paramMap{"uid": uid})
154 switch reply.Code() {
156 _, name = parseUserReply(reply) // caches
158 Cache.SetInvalid(key...)
161 intentMap.NotifyClose(name, key...)
166 var userReplyMutex sync.Mutex
168 func parseUserReply(reply udpapi.APIReply) (UID, string) {
169 userReplyMutex.Lock()
170 defer userReplyMutex.Unlock()
172 if reply.Error() == nil {
173 parts := strings.Split(reply.Lines()[1], "|")
174 id, _ := strconv.ParseInt(parts[0], 10, 32)
176 CacheSet(UID(id), "user", "by-name", parts[1])
177 CacheSet(parts[1], "user", "by-uid", id)
179 if _, err := Cache.Stat("user", id); err != nil {
186 return UID(id), parts[1]