package services import ( "encoding/json" "errors" "fmt" "github.com/wenzhenxi/gorsa" "hongze/hongze_yb/global" models "hongze/hongze_yb/models/tables/report_send_ths_detail" "hongze/hongze_yb/models/tables/voice_broadcast" "hongze/hongze_yb/services/alarm_msg" "hongze/hongze_yb/services/wechat" "hongze/hongze_yb/utils" "io/ioutil" "net/http" "net/url" "strings" "time" ) //func init() { // report, _ := models.GetReportById(572) // SendReportToThs(report) //} var permissionMap map[string]string = map[string]string{ "化里化外日评": "原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱", "股债日评": "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢", "贵金属复盘": "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢", "每日经济数据备忘录": "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢", "宏观商品复盘": "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢", "知白守黑日评": "钢材,铁矿,双焦(焦煤、焦炭)", "有声有色日度闲篇": "有色(铜、铝),有色(锌、铅),镍+不锈钢", "EIA原油库存点评": "原油", "苯乙烯数据点评": "苯乙烯", "API原油库存点评": "原油", "铁矿航运数据点评": "铁矿", "中观需求点评": "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢", "聚酯数据点评": "PTA,MEG", "钢材周度数据点评": "钢材", "寻根知本": "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢", "国际宏观": "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢", "能化百家谈": "原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱", "有色百家谈": "有色(铜、铝),有色(锌、铅),镍+不锈钢", "黑色百家谈": "钢材,铁矿,双焦(焦煤、焦炭)", } // permissionLabelMap 品种与同花顺标签的映射关系 var permissionLabelMap = map[string]string{ "宏观经济": "宏观", "利率债": "利率债", "原油": "原油", "PTA": "PTA", "MEG": "MEG", "织造终端": "织造终端", "甲醇": "甲醇", "聚烯烃": "聚烯烃", "沥青": "沥青", "纯苯+苯乙烯": "纯苯+苯乙烯", "玻璃纯碱": "玻璃纯碱", "钢材": "钢材", "铁矿": "铁矿", "双焦(焦煤、焦炭)": "双焦(焦煤、焦炭)", "有色(锌)": "有色(锌)", "有色(铜、铝)": "有色(铜、铝)", "镍+不锈钢": "镍+不锈钢", "PVC": "PVC", "聚酯": "聚酯", "钴锂": "钴锂", "策略": "策略", "苯乙烯": "纯苯+苯乙烯", "锌": "有色(锌)", "双焦": "双焦(焦煤、焦炭)", "铜/铝": "有色(铜、铝)", "镍/不锈钢": "镍+不锈钢", "成品油": "成品油", "油品": "成品油", "纺服": "织造终端", } // TshResult 同花顺返回信息 type TshResult struct { ErrorCode int `json:"error" description:"错误状态码"` Message string `json:"message" description:"提示信息"` } var ( THS_SendUrl string //同花顺地址url THS_PubKey string //同花顺公钥 ) func init() { THS_PubKey = `-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqugglfCboOEfWtHlGBOW 40a4Y3xOs0MPBwjTOzHgcaWzx5XCc20VftGVXkWlpjs8u4dza/Bp1SV7SJ5Y7U95 jgUOP8Js9Qgp6UVqBJDJf3i1KpjHzlk3ma8zxAYUAdieEUE+SKSxSY+BD9A6lpf5 n+igXLmzR5GeVGFeLzoMhB1+pXgGhW30ao9wPwuRF7DBl+FKa/ACi7iXLiwXVgqT FFi29TKeerEENu3EpMXvPml7tNUiVmVW6d83hlascfbAlkShwuHLSGpLqK7brtg6 jRS9hreKFKb0BUQ4TB26e7IDCstbMRvUp4+OGezexzic5NYPQ8uLo5OTaS7f7PrW ZwIDAQAB -----END PUBLIC KEY-----` if global.CONFIG.Serve.RunMode == "release" { //同花顺正式地址 THS_SendUrl = `https://board.10jqka.com.cn/gateway/ps/syncNews` } else { //同花顺测试地址 THS_SendUrl = `https://mtest.10jqka.com.cn/gateway/ps/syncNews` } } // SendThs 发送消息到同花顺 func SendThs(title, labelStr, abstract, jumpBaseUrl, logoUrl, dataType string) (err error) { return nil defer func() { if err != nil { //fmt.Println(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "发送消息至同花顺失败 ErrMsg:"+err.Error(), utils.EmailSendToUsers) go alarm_msg.SendAlarmMsg("发送消息至同花顺失败 ErrMsg:"+err.Error(), 3) //go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "发送报告至同花顺失败 ErrMsg:"+err.Error(), utils.EmailSendToUsers) } }() pubKey := THS_PubKey sendUrl := THS_SendUrl //标题字符长度截取,最多50位字符 title = utils.SubStr(title, 50) global.LOG.Info(fmt.Sprintf("title:%s", title)) title, err = gorsa.PublicEncrypt(title, pubKey) if err != nil { return } //简介字符长度截取,最多50位字符 abstract = utils.SubStr(abstract, 50) global.LOG.Info(fmt.Sprintf("abstract:%s", abstract)) abstract, err = gorsa.PublicEncrypt(abstract, pubKey) if err != nil { return } // 关联后的标签数据 newLabelList := make([]string, 0) labelList := strings.Split(labelStr, ",") for _, v := range labelList { tmpLabel, ok := permissionLabelMap[v] //判断是否在关联标签里面 if !ok { //如果不在关联标签里面,那么就把原始的值赋值给 tmpLabel = v } newLabelList = append(newLabelList, tmpLabel) } labelStr = strings.Join(newLabelList, ",") global.LOG.Info(fmt.Sprintf("labelStr:%s", labelStr)) label, err := gorsa.PublicEncrypt(labelStr, pubKey) if err != nil { return } // 跳转地址 jumpUrl, err := gorsa.PublicEncrypt(jumpBaseUrl, pubKey) if err != nil { return } picUrl, err := gorsa.PublicEncrypt(logoUrl, pubKey) if err != nil { return } dataTypeEncript, err := gorsa.PublicEncrypt(dataType, pubKey) if err != nil { return } //开始发送 client := http.Client{} form := url.Values{} form.Add("title", title) form.Add("description", abstract) form.Add("label", label) form.Add("url", jumpUrl) form.Add("icon", picUrl) form.Add("dataType", dataTypeEncript) global.LOG.Info(fmt.Sprintf("SendThs parms:%s", form.Encode())) resp, err := client.PostForm(sendUrl, form) if err != nil { return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) //fmt.Println(string(body)) global.LOG.Info(fmt.Sprintf("ThsResult parms:%s", string(body))) //同花顺接口返回数据 var tshResult TshResult err = json.Unmarshal(body, &tshResult) if err != nil { err = errors.New(fmt.Sprint("同花顺接口返回数据转换成结构体异常,Err:", err)) return } if tshResult.ErrorCode != 1 { err = errors.New(fmt.Sprint("发送数据到同花顺接口异常,result:", string(body))) return } return } // SendVoiceBroadcastToThs 发送语音播报到同花顺 func SendVoiceBroadcastToThs(voice *voice_broadcast.VoiceBroadcast) (err error) { defer func() { if err != nil { go alarm_msg.SendAlarmMsg("发送语音播报至同花顺失败 ErrMsg:"+err.Error(), 3) //go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "SendReportMiniToThs发送报告至同花顺失败, ReportId:" + strconv.Itoa(report.Id) + ", ErrMsg:" + err.Error(), utils.EmailSendToUsers) } }() permissionName := "宏观" //写死宏观,默认所有群都推 //小程序跳转地址 jumpBaseUrl := wechat.WxYbAppId + `/pages-voice/voiceDetail?voiceId=` logoUrl := `https://hongze.oss-cn-shanghai.aliyuncs.com/hzyj.png` sendDetail, err := models.GetVoiceSendThsDetailById(voice.BroadcastId, "语音播报") if err != nil && err != utils.ErrNoRow { return } else if err == nil && sendDetail != nil { if sendDetail.Status >= 0 { fmt.Println("重复发送") return } } pushTime := time.Now() //预发送时间 //isPrePush := false //是否预发布 //addTime := time.Minute * 40 //短时间内多次发布报告,每篇报告的间隔时间(目前暂定40分钟,只有日度点评的报告需要限制) ////获取距离现在最近的一条发送成功失败记录 //latelySendDetail, err := models.GetLatelyReportSendThsDetail() ////如果存在最近一条发送记录,那么去校验时间 //if (err == nil && latelySendDetail != nil) || err == utils.ErrNoRow { // pushTime = latelySendDetail.PushTime.Add(addTime) // //如果最近一条的发送记录 的 (发送时间 + 每篇报告的间隔时间) 晚于 当前时间 // if pushTime.After(time.Now()) { // isPrePush = true // } else { // pushTime = time.Now() // } //} // //if isPrePush { //预发布,只添加预发布记录,不立马发送报告,等待定时任务推送消息给同花顺 // newSendDetail := &models.ReportSendThsDetail{ // ReportId: voice.BroadcastId, // ReportType: "语音播报", // Status: 2, // PushTime: pushTime, // CreateTime: time.Now(), // } // _, tmpErr := models.AddReportSendThsDetail(newSendDetail) // if tmpErr != nil { // err = tmpErr // return // } //} else { // newSendDetail := &models.ReportSendThsDetail{ // ReportId: voice.BroadcastId, // ReportType: "语音播报", // Status: 0, // PushTime: pushTime, // CreateTime: time.Now(), // } // sendDetailId, tmpErr := models.AddReportSendThsDetail(newSendDetail) // if tmpErr != nil { // err = tmpErr // return // } // //及时发送 // dataType := "2" //内容类型:1文字 2小程序 // err = SendThs(voice.BroadcastName, permissionName, voice.BroadcastName, fmt.Sprint(jumpBaseUrl, voice.BroadcastId), logoUrl, dataType) // if err != nil { // _ = models.ModifyReportSendThsDetailStatus(int(sendDetailId), -1, err.Error()) // return // } // _ = models.ModifyReportSendThsDetailStatus(int(sendDetailId), 1, "") //} newSendDetail := &models.ReportSendThsDetail{ ReportId: voice.BroadcastId, ReportType: "语音播报", Status: 0, PushTime: pushTime, CreateTime: time.Now(), Title: voice.BroadcastName, LabelStr: permissionName, RecordStatus: 0, MsgType: 2, Content: voice.BroadcastName, JumpUrl: fmt.Sprint(jumpBaseUrl, voice.BroadcastId), Pic: logoUrl, } sendDetailId, tmpErr := models.AddReportSendThsDetail(newSendDetail) if tmpErr != nil { err = tmpErr return } //及时发送 dataType := "2" //内容类型:1文字 2小程序 err = SendThs(voice.BroadcastName, permissionName, voice.BroadcastName, fmt.Sprint(jumpBaseUrl, voice.BroadcastId), logoUrl, dataType) if err != nil { _ = models.ModifyReportSendThsDetailStatus(int(sendDetailId), -1, err.Error()) return } _ = models.ModifyReportSendThsDetailStatus(int(sendDetailId), 1, "") return }