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 UserByName(name string) *User {
24 if CacheGet(&uid, "user", "by-name", name) == nil {
30 func (adb *AniDB) GetCurrentUser() <-chan *User {
31 ch := make(chan *User, 1)
33 if adb.udp.credentials == nil {
39 return adb.GetUserByName(decrypt(adb.udp.credentials.username))
42 // This is an (almost) entirely local representation.
43 func (adb *AniDB) GetUserByID(uid UID) <-chan *User {
44 key := []fscache.CacheKey{"user", uid}
45 ch := make(chan *User, 1)
53 ic := make(chan notification, 1)
54 go func() { ch <- (<-ic).(*User); close(ch) }()
55 if intentMap.Intent(ic, key...) {
59 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
60 intentMap.NotifyClose((*User)(nil), key...)
66 if CacheGet(&user, key...) == nil {
67 intentMap.NotifyClose(user, key...)
70 <-adb.GetUserName(uid)
72 CacheGet(&user, key...)
73 intentMap.NotifyClose(user)
78 func (adb *AniDB) GetUserByName(username string) <-chan *User {
79 ch := make(chan *User, 1)
88 ch <- <-adb.GetUserByID(<-adb.GetUserUID(username))
94 func (adb *AniDB) GetUserUID(username string) <-chan UID {
95 key := []fscache.CacheKey{"user", "by-name", username}
96 ch := make(chan UID, 1)
104 ic := make(chan notification, 1)
105 go func() { ch <- (<-ic).(UID); close(ch) }()
106 if intentMap.Intent(ic, key...) {
110 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
111 intentMap.NotifyClose((UID)(0), key...)
116 switch ts, err := Cache.Get(&uid, key...); {
117 case err == nil && time.Now().Sub(ts) < UIDCacheDuration:
118 intentMap.NotifyClose(uid, key...)
123 reply := <-adb.udp.SendRecv("USER",
124 paramMap{"user": username})
126 switch reply.Code() {
128 uid, _ = parseUserReply(reply) // caches
130 Cache.SetInvalid(key...)
133 intentMap.NotifyClose(uid, key...)
138 func (adb *AniDB) GetUserName(uid UID) <-chan string {
139 key := []fscache.CacheKey{"user", "by-uid", uid}
140 ch := make(chan string, 1)
148 ic := make(chan notification, 1)
149 go func() { ch <- (<-ic).(string); close(ch) }()
150 if intentMap.Intent(ic, key...) {
154 if !Cache.IsValid(InvalidKeyCacheDuration, key...) {
155 intentMap.NotifyClose("", key...)
160 switch ts, err := Cache.Get(&name, key...); {
161 case err == nil && time.Now().Sub(ts) < UIDCacheDuration:
162 intentMap.NotifyClose(name, key...)
167 reply := <-adb.udp.SendRecv("USER",
168 paramMap{"uid": uid})
170 switch reply.Code() {
172 _, name = parseUserReply(reply) // caches
174 Cache.SetInvalid(key...)
177 intentMap.NotifyClose(name, key...)
182 var userReplyMutex sync.Mutex
184 func parseUserReply(reply udpapi.APIReply) (UID, string) {
185 userReplyMutex.Lock()
186 defer userReplyMutex.Unlock()
188 if reply.Error() == nil {
189 parts := strings.Split(reply.Lines()[1], "|")
190 id, _ := strconv.ParseInt(parts[0], 10, 32)
192 CacheSet(UID(id), "user", "by-name", parts[1])
193 CacheSet(parts[1], "user", "by-uid", id)
195 if _, err := Cache.Stat("user", id); err != nil {
202 return UID(id), parts[1]