|
@@ -0,0 +1,239 @@
|
|
|
+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"
|
|
|
+ "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,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱",
|
|
|
+ "有色百家谈": "有色(铜、铝),有色(锌、铅),镍+不锈钢",
|
|
|
+ "黑色百家谈": "钢材,铁矿,双焦(焦煤、焦炭)",
|
|
|
+}
|
|
|
+
|
|
|
+// 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) {
|
|
|
+ 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
|
|
|
+ }
|
|
|
+
|
|
|
+ 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)
|
|
|
+ }
|
|
|
+ }()
|
|
|
+
|
|
|
+ //小程序跳转地址
|
|
|
+ jumpBaseUrl := wechat.WxYbAppId + `/pages/voice/voice?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, voice.VarietyName, 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
|
|
|
+}
|