4 "github.com/Kovensky/go-anidb/udp"
5 "github.com/Kovensky/go-fscache"
14 func (uid UID) User() *User {
16 if CacheGet(&u, "user", uid) == nil {
22 func (adb *AniDB) GetCurrentUser() <-chan *User {
23 ch := make(chan *User, 1)
25 if adb.udp.credentials == nil {
31 return adb.GetUserByName(decrypt(adb.udp.credentials.username))
34 // This is an (almost) entirely local representation.
35 func (adb *AniDB) GetUserByID(uid UID) <-chan *User {
36 key := []fscache.CacheKey{"user", uid}
37 ch := make(chan *User, 1)
45 ic := make(chan notification, 1)
46 go func() { ch <- (<-ic).(*User); close(ch) }()
47 if intentMap.Intent(ic, key...) {
51 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
52 intentMap.NotifyClose((*User)(nil), key...)
58 if CacheGet(&user, key...) == nil {
59 intentMap.NotifyClose(user, key...)
62 <-adb.GetUserName(uid)
64 CacheGet(&user, key...)
65 intentMap.NotifyClose(user)
70 func (adb *AniDB) GetUserByName(username string) <-chan *User {
71 ch := make(chan *User, 1)
80 ch <- <-adb.GetUserByID(<-adb.GetUserUID(username))
86 func (adb *AniDB) GetUserUID(username string) <-chan UID {
87 key := []fscache.CacheKey{"user", "by-name", username}
88 ch := make(chan UID, 1)
96 ic := make(chan notification, 1)
97 go func() { ch <- (<-ic).(UID); close(ch) }()
98 if intentMap.Intent(ic, key...) {
102 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
103 intentMap.NotifyClose((UID)(0), key...)
108 switch ts, err := Cache.Get(&uid, key...); {
109 case err == nil && time.Now().Sub(ts) < UIDCacheDuration:
110 intentMap.NotifyClose(uid, key...)
115 reply := <-adb.udp.SendRecv("USER",
116 paramMap{"user": username})
118 switch reply.Code() {
120 uid, _ = parseUserReply(reply) // caches
122 Cache.SetInvalid(key...)
125 intentMap.NotifyClose(uid, key...)
130 func (adb *AniDB) GetUserName(uid UID) <-chan string {
131 key := []fscache.CacheKey{"user", "by-uid", uid}
132 ch := make(chan string, 1)
140 ic := make(chan notification, 1)
141 go func() { ch <- (<-ic).(string); close(ch) }()
142 if intentMap.Intent(ic, key...) {
146 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
147 intentMap.NotifyClose("", key...)
152 switch ts, err := Cache.Get(&name, key...); {
153 case err == nil && time.Now().Sub(ts) < UIDCacheDuration:
154 intentMap.NotifyClose(name, key...)
159 reply := <-adb.udp.SendRecv("USER",
160 paramMap{"uid": uid})
162 switch reply.Code() {
164 _, name = parseUserReply(reply) // caches
166 Cache.SetInvalid(key...)
169 intentMap.NotifyClose(name, key...)
174 var userReplyMutex sync.Mutex
176 func parseUserReply(reply udpapi.APIReply) (UID, string) {
177 userReplyMutex.Lock()
178 defer userReplyMutex.Unlock()
180 if reply.Error() == nil {
181 parts := strings.Split(reply.Lines()[1], "|")
182 id, _ := strconv.ParseInt(parts[0], 10, 32)
184 CacheSet(UID(id), "user", "by-name", parts[1])
185 CacheSet(parts[1], "user", "by-uid", id)
187 if _, err := Cache.Stat("user", id); err != nil {
194 return UID(id), parts[1]