/** * @Author: jager * @Email: lhj168os@gmail.com * @File: fund * @Date: 2021/12/1 3:05 下午 * @package: fund * @Version: v1.0.0 * * @Description: * */ package fund import ( "encoding/json" "fmt" "github.com/jageros/hawox/errcode" "github.com/jageros/hawox/httpc" "github.com/jageros/hawox/logx" "regexp" "strconv" "sync" "time" ) const ( baseUrl = "http://fundgz.1234567.com.cn/js/%s.js" ) var ( jsonStr = regexp.MustCompile(`{(.*?)}`) fds = &funds{fdsMap: map[string]*fund{}} ) type fund struct { Code string `json:"fundcode"` FName string `json:"name"` UnitVal string `json:"dwjz"` EstimateVal string `json:"gsz"` RisePer string `json:"gszzl"` UpdateTime string `json:"gztime"` CheckTime time.Time } func (f *fund) Name() string { return f.FName } func (f *fund) Update() error { url := fmt.Sprintf(baseUrl, f.Code) result, err := httpc.Request(httpc.GET, url, httpc.FORM, nil, nil) if err != nil { return err } ss := jsonStr.FindStringSubmatch(string(result)) if len(ss) <= 0 { return errcode.New(404, "找不到基金:"+f.Code) } ff := &fund{} err = json.Unmarshal([]byte(ss[0]), ff) if err == nil { f.FName = ff.FName f.UnitVal = ff.UnitVal f.EstimateVal = ff.EstimateVal f.RisePer = ff.RisePer f.UpdateTime = ff.UpdateTime f.CheckTime = time.Now() } return err } func (f *fund) Msg() string { now := time.Now() h := now.Hour() if h > 9 && h < 15 && now.Sub(f.CheckTime) > time.Minute*5 { err := f.Update() if err != nil { logx.Error(err) } } var rise string last, err1 := strconv.ParseFloat(f.UnitVal, 64) cur, err2 := strconv.ParseFloat(f.EstimateVal, 64) if err1 == nil && err2 == nil { rise = fmt.Sprintf("%.5f", cur-last) } msg := fmt.Sprintf(msgTemplate, f.FName, f.Code, f.UpdateTime, f.UnitVal, f.EstimateVal, rise, f.RisePer) return msg } type funds struct { fdsMap map[string]*fund mx sync.RWMutex } func (fs *funds) getFund(code string) *fund { fs.mx.RLock() defer fs.mx.RUnlock() if fd, ok := fs.fdsMap[code]; ok { return fd } return nil } func (fs *funds) addFund(fd *fund) { fs.mx.Lock() defer fs.mx.Unlock() fs.fdsMap[fd.Code] = fd } func Clear() { fds.mx.Lock() defer fds.mx.Unlock() fds = &funds{ fdsMap: map[string]*fund{}, } } func FundsMsg(codes ...string) string { if len(codes) <= 0 { return "" } //var msg = "基金定投估值 >>>\n" msg := "" for _, code := range codes { fd := fds.getFund(code) if fd == nil { fd_, err := NewFund(code) if err == nil { fd = fd_ fds.addFund(fd_) } else { logx.Error(err) continue } } msg += fd.Msg() } return msg } func NewFund(code string) (*fund, error) { url := fmt.Sprintf(baseUrl, code) result, err := httpc.Request(httpc.GET, url, httpc.FORM, nil, nil) if err != nil { return nil, err } ss := jsonStr.FindStringSubmatch(string(result)) if len(ss) <= 0 { return nil, errcode.New(404, "找不到基金:"+code) } ff := &fund{} err = json.Unmarshal([]byte(ss[0]), ff) return ff, err } const msgTemplate = `%s(%s) 更新时间:%s 单位净值:%s 估算净值:%s 估算涨幅:(%s) %s%% ` type fundArg struct { codes []string } func NewFundArg(codes ...string) *fundArg { return &fundArg{ codes: codes, } } func (fa *fundArg) Arg(openid string) map[string]interface{} { msg := FundsMsg(fa.codes...) if msg == "" { return nil } arg := map[string]interface{}{ "touser": openid, "template_id": "SQXWp3RiYySb2GYG-vMYDsSIm-KZNM9szVpFOryUQGQ", "data": map[string]interface{}{ "keyword": map[string]interface{}{ "value": msg, "color": "#173177", }, }, } return arg }