| @@ -0,0 +1,87 @@ | |||
| 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 | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| 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") | |||
| } | |||
| @@ -0,0 +1,20 @@ | |||
| { | |||
| "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" | |||
| } | |||
| ] | |||
| } | |||