You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
3.6 KiB
Go
194 lines
3.6 KiB
Go
/**
|
|
* @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.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%%
|
|
|
|
`
|
|
|
|
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
|
|
}
|