|
|
@ -9,10 +9,13 @@ import (
|
|
|
|
"stock/cfg"
|
|
|
|
"stock/cfg"
|
|
|
|
"strconv"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
var (
|
|
|
|
baseUrl = "https://hq.sinajs.cn/"
|
|
|
|
baseUrl = "https://hq.sinajs.cn/"
|
|
|
|
|
|
|
|
fds *stocks
|
|
|
|
|
|
|
|
mx sync.RWMutex
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type IStock interface {
|
|
|
|
type IStock interface {
|
|
|
@ -28,6 +31,14 @@ type stock struct {
|
|
|
|
nowRise float64
|
|
|
|
nowRise float64
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (s *stock) Code() string {
|
|
|
|
|
|
|
|
return s.code
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (s *stock) Name() string {
|
|
|
|
|
|
|
|
return s.values[0]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *stock) update(values []string) {
|
|
|
|
func (s *stock) update(values []string) {
|
|
|
|
s.values = values
|
|
|
|
s.values = values
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -130,41 +141,84 @@ func (s *stock) Msg() string {
|
|
|
|
return msg
|
|
|
|
return msg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ==========================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func Init(codes ...string) error {
|
|
|
|
|
|
|
|
fds = &stocks{}
|
|
|
|
|
|
|
|
return fds.AddCodes(codes...)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type stocks struct {
|
|
|
|
type stocks struct {
|
|
|
|
codes []string
|
|
|
|
//codes []string
|
|
|
|
ss []*stock
|
|
|
|
//ss []*stock
|
|
|
|
|
|
|
|
stkMap map[string]*stock
|
|
|
|
|
|
|
|
mx sync.RWMutex
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (sk *stocks) getStocks(codes ...string) *stocks {
|
|
|
|
|
|
|
|
var stks = &stocks{}
|
|
|
|
|
|
|
|
for _, code := range codes {
|
|
|
|
|
|
|
|
stks.stkMap[code] = sk.stkMap[code]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return stks
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (sk *stocks) Codes() []string {
|
|
|
|
|
|
|
|
var codes []string
|
|
|
|
|
|
|
|
for code := range sk.stkMap {
|
|
|
|
|
|
|
|
codes = append(codes, code)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return codes
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (sk *stocks) AddCodes(codes ...string) error {
|
|
|
|
|
|
|
|
sk.mx.Lock()
|
|
|
|
|
|
|
|
defer sk.mx.Unlock()
|
|
|
|
|
|
|
|
var cds []string
|
|
|
|
|
|
|
|
for _, code := range codes {
|
|
|
|
|
|
|
|
if _, ok := sk.stkMap[code]; ok {
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
cds = append(cds, code)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
stks, err := newStocks(cds...)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, stk := range stks {
|
|
|
|
|
|
|
|
sk.stkMap[stk.Code()] = stk
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (sk *stocks) Clear() {
|
|
|
|
func (sk *stocks) Clear() {
|
|
|
|
if len(sk.ss) <= 0 {
|
|
|
|
sk.mx.Lock()
|
|
|
|
return
|
|
|
|
defer sk.mx.Unlock()
|
|
|
|
|
|
|
|
for _, fd := range fds.stkMap {
|
|
|
|
|
|
|
|
fd.lastRise = 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sk.ss = []*stock{}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (sk *stocks) Update() error {
|
|
|
|
func (sk *stocks) Update() error {
|
|
|
|
str, err := getStockStr(sk.codes)
|
|
|
|
sk.mx.Lock()
|
|
|
|
|
|
|
|
sk.mx.Unlock()
|
|
|
|
|
|
|
|
str, err := getStockStr(sk.Codes())
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
strs := strings.Split(str, ";\n")
|
|
|
|
strs := strings.Split(str, ";\n")
|
|
|
|
if len(sk.ss) == 0 {
|
|
|
|
|
|
|
|
sk.ss = []*stock{}
|
|
|
|
|
|
|
|
for _, s := range strs {
|
|
|
|
for _, s := range strs {
|
|
|
|
ss := strings.Split(s, "\"")
|
|
|
|
ss := strings.Split(s, "\"")
|
|
|
|
if len(ss) >= 2 {
|
|
|
|
if len(ss) >= 2 {
|
|
|
|
v := &stock{
|
|
|
|
v := &stock{
|
|
|
|
|
|
|
|
code: ss[0][13:19],
|
|
|
|
values: strings.Split(ss[1], ","),
|
|
|
|
values: strings.Split(ss[1], ","),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sk.ss = append(sk.ss, v)
|
|
|
|
if skk, ok := sk.stkMap[v.code]; ok {
|
|
|
|
}
|
|
|
|
skk.update(v.values)
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
l := len(sk.ss)
|
|
|
|
sk.stkMap[v.code] = v
|
|
|
|
for i, s := range strs {
|
|
|
|
|
|
|
|
ss := strings.Split(s, "\"")
|
|
|
|
|
|
|
|
if len(ss) >= 2 && i < l {
|
|
|
|
|
|
|
|
sk.ss[i].update(strings.Split(ss[1], ","))
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -173,8 +227,10 @@ func (sk *stocks) Update() error {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (sk *stocks) Msg() string {
|
|
|
|
func (sk *stocks) Msg() string {
|
|
|
|
|
|
|
|
sk.mx.RLock()
|
|
|
|
|
|
|
|
defer sk.mx.RUnlock()
|
|
|
|
var resp string
|
|
|
|
var resp string
|
|
|
|
for _, s := range sk.ss {
|
|
|
|
for _, s := range sk.stkMap {
|
|
|
|
if s.notify() {
|
|
|
|
if s.notify() {
|
|
|
|
msg := s.Msg()
|
|
|
|
msg := s.Msg()
|
|
|
|
resp = resp + msg + "\n"
|
|
|
|
resp = resp + msg + "\n"
|
|
|
@ -183,33 +239,65 @@ func (sk *stocks) Msg() string {
|
|
|
|
return resp
|
|
|
|
return resp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type IArg interface {
|
|
|
|
func (sk *stocks) Arg(openid string) map[string]interface{} {
|
|
|
|
Arg(openId string) map[string]interface{}
|
|
|
|
arg := map[string]interface{}{
|
|
|
|
|
|
|
|
"touser": openid,
|
|
|
|
|
|
|
|
"template_id": "yWuLbhAy7TTuqdeB9-VS6CR_t2rZQ8MHkJ62MF3VlS8",
|
|
|
|
|
|
|
|
"data": map[string]interface{}{
|
|
|
|
|
|
|
|
"keyword": map[string]interface{}{
|
|
|
|
|
|
|
|
"value": sk.Msg(),
|
|
|
|
|
|
|
|
"color": "#173177",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return arg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (sk *stocks) ForEachStock(f func(stk IArg) error) error {
|
|
|
|
func GetStocks(codes ...string) (*stocks, error) {
|
|
|
|
for _, k := range sk.ss {
|
|
|
|
if len(codes) <= 0 {
|
|
|
|
err := f(k)
|
|
|
|
return nil, errcode.New(1, "股票代码为空")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mx.Lock()
|
|
|
|
|
|
|
|
defer mx.Unlock()
|
|
|
|
|
|
|
|
if fds == nil {
|
|
|
|
|
|
|
|
fds = &stocks{}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
err := fds.AddCodes(codes...)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fds.getStocks(codes...), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
|
|
|
|
|
|
|
|
func Update() error {
|
|
|
|
|
|
|
|
return fds.Update()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func NewStocks(codes ...string) (*stocks, error) {
|
|
|
|
func Clear() {
|
|
|
|
if len(codes) <= 0 {
|
|
|
|
fds.Clear()
|
|
|
|
return nil, errcode.New(1, "股票代码为空")
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
s := &stocks{
|
|
|
|
func newStocks(codes ...string) ([]*stock, error) {
|
|
|
|
codes: codes,
|
|
|
|
if len(codes) <= 0 {
|
|
|
|
|
|
|
|
return nil, errcode.New(1, "股票代码为空")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err := s.Update()
|
|
|
|
str, err := getStockStr(codes)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return s, nil
|
|
|
|
strs := strings.Split(str, ";\n")
|
|
|
|
|
|
|
|
var stks []*stock
|
|
|
|
|
|
|
|
for _, s := range strs {
|
|
|
|
|
|
|
|
ss := strings.Split(s, "\"")
|
|
|
|
|
|
|
|
if len(ss) >= 2 {
|
|
|
|
|
|
|
|
v := &stock{
|
|
|
|
|
|
|
|
values: strings.Split(ss[1], ","),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
stks = append(stks, v)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return stks, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func addPrefix(code string) string {
|
|
|
|
func addPrefix(code string) string {
|
|
|
@ -251,66 +339,67 @@ const msgTemplate = `%s
|
|
|
|
前五总买单:%s 前五总卖单:%s
|
|
|
|
前五总买单:%s 前五总卖单:%s
|
|
|
|
`
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
|
|
func (s *stock) Arg(openId string) map[string]interface{} {
|
|
|
|
//
|
|
|
|
|
|
|
|
//func (s *stock) Arg(openId string) map[string]interface{} {
|
|
|
|
arg := map[string]interface{}{
|
|
|
|
//
|
|
|
|
"touser": openId,
|
|
|
|
// arg := map[string]interface{}{
|
|
|
|
"template_id": "L7fOGJURj-1HF4cIpFizCOOiAMqER3PG-pfgn37Dalw",
|
|
|
|
// "touser": openId,
|
|
|
|
|
|
|
|
// "template_id": "L7fOGJURj-1HF4cIpFizCOOiAMqER3PG-pfgn37Dalw",
|
|
|
|
"data": map[string]interface{}{
|
|
|
|
//
|
|
|
|
"first": map[string]interface{}{
|
|
|
|
// "data": map[string]interface{}{
|
|
|
|
"value": s.values[0],
|
|
|
|
// "first": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": s.values[0],
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword1": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": fmt.Sprintf("%s %s", s.values[30], s.values[31]),
|
|
|
|
// "keyword1": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": fmt.Sprintf("%s %s", s.values[30], s.values[31]),
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword2": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": s.values[2],
|
|
|
|
// "keyword2": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": s.values[2],
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword3": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": s.values[1],
|
|
|
|
// "keyword3": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": s.values[1],
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword4": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": s.values[3],
|
|
|
|
// "keyword4": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": s.values[3],
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword5": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": s.rise(),
|
|
|
|
// "keyword5": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": s.rise(),
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword6": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": s.values[4],
|
|
|
|
// "keyword6": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": s.values[4],
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword7": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": s.values[5],
|
|
|
|
// "keyword7": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": s.values[5],
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword8": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": s.tradingVolume(),
|
|
|
|
// "keyword8": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": s.tradingVolume(),
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword9": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": numFormat(s.values[9]),
|
|
|
|
// "keyword9": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": numFormat(s.values[9]),
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword10": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": s.buyCount(),
|
|
|
|
// "keyword10": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": s.buyCount(),
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"keyword11": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": s.sellCount(),
|
|
|
|
// "keyword11": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": s.sellCount(),
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
"remark": map[string]interface{}{
|
|
|
|
// },
|
|
|
|
"value": "欢迎再次购买!",
|
|
|
|
// "remark": map[string]interface{}{
|
|
|
|
"color": "#173177",
|
|
|
|
// "value": "欢迎再次购买!",
|
|
|
|
},
|
|
|
|
// "color": "#173177",
|
|
|
|
},
|
|
|
|
// },
|
|
|
|
}
|
|
|
|
// },
|
|
|
|
return arg
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
// return arg
|
|
|
|
|
|
|
|
//}
|
|
|
|