| package main | |||||
| import ( | |||||
| "encoding/json" | |||||
| "fmt" | |||||
| "io/ioutil" | |||||
| "log" | |||||
| "net/http" | |||||
| "time" | |||||
| ) | |||||
| type kfInfo struct { | |||||
| Acc string `json:"kf_account"` // | |||||
| Nick string `json:"kf_nick"` // | |||||
| ID int `json:"kf_id"` // | |||||
| Avatar string `json:"kf_headimgurl"` // | |||||
| } | |||||
| //KFUserList a list of kf users | |||||
| type kfUserList struct { | |||||
| KfList []kfInfo `json:"kf_list"` | |||||
| } | |||||
| //KFCache KF user's info cache | |||||
| type kfCache struct { | |||||
| Name2Acc map[string]string //map nickname to account id | |||||
| ID2Acc map[int]string //map from id to acc | |||||
| Users kfUserList | |||||
| UpdateAt int32 //time stamp | |||||
| Expire int32 //time stamp | |||||
| } | |||||
| func getKFlistURL() string { | |||||
| atk, _ := GetAccessToken() | |||||
| return fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=%s", atk) | |||||
| } | |||||
| func (m *kfCache) getKFUsers() (err error) { | |||||
| jstr, err := m.kfGetListJSON() | |||||
| err = json.Unmarshal([]byte(jstr), &m.Users) | |||||
| return | |||||
| } | |||||
| func (m *kfCache) kfAcc(nickname string) (acc string) { | |||||
| m.kfRenewList() | |||||
| return m.Name2Acc[nickname] | |||||
| } | |||||
| func (m *kfCache) kfGetListJSON() (jstr string, err error) { | |||||
| url := getKFlistURL() | |||||
| resp, err := http.Get(url) | |||||
| if err != nil { | |||||
| return | |||||
| } | |||||
| b, err := ioutil.ReadAll(resp.Body) | |||||
| if err == nil { | |||||
| jstr = string(b) | |||||
| } | |||||
| return | |||||
| } | |||||
| func (m *kfCache) kfRenewList() { | |||||
| if m.Expire == 0 || m.UpdateAt == 0 || m.Expire < m.UpdateAt { | |||||
| log.Println("Renew Kf Info List") | |||||
| err := m.getKFUsers() | |||||
| if err == nil { | |||||
| m.Name2Acc = map[string]string{} | |||||
| m.ID2Acc = map[int]string{} | |||||
| for _, v := range m.Users.KfList { | |||||
| m.Name2Acc[v.Nick] = v.Acc | |||||
| m.ID2Acc[v.ID] = v.Acc | |||||
| } | |||||
| m.UpdateAt = int32(time.Now().Unix()) | |||||
| m.Expire = m.UpdateAt + 1200 //20 minutes | |||||
| } | |||||
| } | |||||
| } | |||||
| func (m *kfCache) kfGetInfo(nick string) (r kfInfo) { | |||||
| m.kfRenewList() | |||||
| for _, v := range m.Users.KfList { | |||||
| if nick == v.Nick { | |||||
| return v | |||||
| } | |||||
| } | |||||
| return | |||||
| } |
| package main | |||||
| import ( | |||||
| "encoding/json" | |||||
| "testing" | |||||
| "time" | |||||
| ) | |||||
| func TestKfList(t *testing.T) { | |||||
| SetupConfig() | |||||
| now := int32(time.Now().Unix()) | |||||
| s := kfCache{} | |||||
| r := s.kfGetInfo("孙鹏") //will trigger load info | |||||
| AssertEqual(t, r.Acc, "kf2001@gh_f09231355c68", "kf account str mismatch") | |||||
| AssertEqual(t, r.ID, 2001, "kf account id should be 2001") | |||||
| avatarurl := "http://mmbiz.qpic.cn/mmbiz_jpg/WiaVAicTdo7zMrD65vOsqRVQL6YlSPkzhp6y8ksIjd3yOfYu2xe9w7jAbdBIFoic3Bh4fWkvUzOW29u9FN0tDXG2Q/300?wx_fmt=jpeg" | |||||
| AssertEqual(t, r.Avatar, avatarurl, "kf avatar url mismatch") | |||||
| //get kfacc by name | |||||
| id := s.kfAcc("孙鹏") | |||||
| AssertEqual(t, id, "kf2001@gh_f09231355c68", "kf account id should be kf2001@gh_f09231355c68") | |||||
| //test cache | |||||
| AssertEqual(t, s.Expire > s.UpdateAt, true, "expire should after update") | |||||
| AssertEqual(t, s.UpdateAt >= now, true, "expire should after update") | |||||
| orig := s | |||||
| s.kfRenewList() | |||||
| s.kfRenewList() | |||||
| AssertEqual(t, orig.Expire, s.Expire, "time stamp should still be the same") | |||||
| } | |||||
| func TestJsonStructure(t *testing.T) { | |||||
| sample := ` | |||||
| { | |||||
| "kf_list": [ | |||||
| { | |||||
| "kf_account": "kf2001@gh_f09231355c68", | |||||
| "kf_headimgurl": "http:\/\/mmbiz.qpic.cn\/mmbiz_jpg\/WiaVAicTdo7zMrD65vOsqRVQL6YlSPkzhp6y8ksIjd3yOfYu2xe9w7jAbdBIFoic3Bh4fWkvUzOW29u9FN0tDXG2Q\/300?wx_fmt=jpeg", | |||||
| "kf_id": 2001, | |||||
| "kf_nick": "孙鹏", | |||||
| "kf_wx": "lawipac" | |||||
| }, | |||||
| { | |||||
| "kf_account": "kf2002@gh_f09231355c68", | |||||
| "kf_headimgurl": "http:\/\/mmbiz.qpic.cn\/mmbiz_jpg\/WiaVAicTdo7zMZVRDmRUIkaV0Uiardfw9VbvqicgtWAbM6jYKaDdScKAtahICB204fCiaz8Ucb3VyGIjKEWicIjhMzUw\/300?wx_fmt=jpeg", | |||||
| "kf_id": 2002, | |||||
| "kf_nick": "理事", | |||||
| "invite_wx": "x707184846", | |||||
| "invite_expire_time": 1495195006, | |||||
| "invite_status": "expired" | |||||
| } | |||||
| ] | |||||
| } | |||||
| ` | |||||
| k := kfUserList{} | |||||
| err := json.Unmarshal([]byte(sample), &k) | |||||
| AssertEqual(t, err, nil, "decode json should have no error") | |||||
| AssertEqual(t, len(k.KfList), 2, "should have 2 kf users") | |||||
| AssertEqual(t, k.KfList[0].Acc, "kf2001@gh_f09231355c68", "first acc mismatch") | |||||
| AssertEqual(t, k.KfList[1].Acc, "kf2002@gh_f09231355c68", "second acc mismatch") | |||||
| } |
| { | |||||
| "kf_list": [ | |||||
| { | |||||
| "kf_account": "kf2001@gh_f09231355c68", | |||||
| "kf_headimgurl": "http:\/\/mmbiz.qpic.cn\/mmbiz_jpg\/WiaVAicTdo7zMrD65vOsqRVQL6YlSPkzhp6y8ksIjd3yOfYu2xe9w7jAbdBIFoic3Bh4fWkvUzOW29u9FN0tDXG2Q\/300?wx_fmt=jpeg", | |||||
| "kf_id": 2001, | |||||
| "kf_nick": "孙鹏", | |||||
| "kf_wx": "lawipac" | |||||
| }, | |||||
| { | |||||
| "kf_account": "kf2002@gh_f09231355c68", | |||||
| "kf_headimgurl": "http:\/\/mmbiz.qpic.cn\/mmbiz_jpg\/WiaVAicTdo7zMZVRDmRUIkaV0Uiardfw9VbvqicgtWAbM6jYKaDdScKAtahICB204fCiaz8Ucb3VyGIjKEWicIjhMzUw\/300?wx_fmt=jpeg", | |||||
| "kf_id": 2002, | |||||
| "kf_nick": "理事", | |||||
| "invite_wx": "x707184846", | |||||
| "invite_expire_time": 1495195006, | |||||
| "invite_status": "expired" | |||||
| } | |||||
| ] | |||||
| } |