package services import ( "encoding/json" "errors" "fmt" "github.com/PuerkitoBio/goquery" "github.com/rdlucklib/rdluck_tools/http" "hongze/hongze_open_api/models/tables" "hongze/hongze_open_api/services/alarm_msg" "hongze/hongze_open_api/utils" "html" "strconv" "strings" "time" ) type EnPolicyReportDataListResp struct { Code int `json:"code"` Msg string `json:"msg"` Data []EnPolicyReportDataListItem `json:"data"` Pagination EnPolicyReportDataPage `json:"pagination"` } type EnPolicyReportDataDetailResp struct { Code int `json:"code"` Msg string `json:"msg"` Data EnPolicyReportDataListItem `json:"data"` } type EnPolicyReportDataPage struct { Total int `json:"total"` Page int `json:"page"` PageSize int `json:"page_size"` PageTotal int `json:"page_total"` } type EnPolicyReportDataListItem struct { Id int `json:"id"` Title string `json:"title"` TitleEn string `json:"title_en"` Frequency string `json:"frequency"` CreateDate time.Time `json:"create_date"` UpdateDate time.Time `json:"update_date"` PublishDate time.Time `json:"publish_date"` PublishStatus int `json:"publish_status"` VerifyStatus int `json:"verify_status"` PublishArea string `json:"publish_area"` AccessLevel int `json:"access_level"` IsActive bool `json:"is_active"` AuthorPhoneNumber string `json:"author_phone_number"` Cover string `json:"cover"` IndustryId int `json:"industry_id"` ContentId int `json:"content_id"` TypeId int `json:"type_id"` FieldId int `json:"field_id"` SeriesId int `json:"series_id"` File interface{} `json:"file"` Stock []string `json:"stock"` IsFocused int `json:"is_focused"` Content EnPolicyReportDataListItemContent `json:"content"` Industry EnPolicyReportDataListItemInfo `json:"industry"` Type EnPolicyReportDataListItemInfo `json:"type"` Field EnPolicyReportDataListItemInfoMore `json:"field"` Series EnPolicyReportDataListItemInfoMore `json:"series"` Author EnPolicyReportDataListItemAuthor `json:"author"` } type EnPolicyReportDataListItemContent struct { Id int `json:"id"` Body string `json:"body"` Abstract string `json:"abstract"` Annotation string `json:"annotation"` } type EnPolicyReportDataListItemInfo struct { Id int `json:"id"` Name string `json:"name"` Description string `json:"description"` } type EnPolicyReportDataListItemInfoMore struct { Id int `json:"id"` Name string `json:"name"` Description string `json:"description"` IndustryId int `json:"industry_id"` } type EnPolicyReportDataListItemAuthor struct { PhoneNumber string `json:"phone_number"` Name string `json:"name"` } // PullEnglishPolicyReportSingle 根据报告ID 拉取报告 func PullEnglishPolicyReportSingle(sourceId int) (ret tables.PullEnglishPolicyDataResp, err error, msg string) { defer func() { if err != nil { go alarm_msg.SendAlarmMsg("拉取单个英文策略报告失败,Err:"+err.Error()+";msg:"+msg, 3) utils.FileLog.Info(fmt.Sprintf("拉取单个英文策略报告失败 PullEnglishPolicyReportSingle,Err:%s,%s", err.Error(), msg)) } }() //获取已插入的报告ID,避免重复插入 _, err = tables.GetEnglishPolicyReportBySourceReportId(sourceId) if err != nil { if err.Error() == utils.ErrNoRow() { err = nil } else { msg = "查询已存在的英文策略报告列表接口失败" return } } else { // 该报告已存在 return } originDetail, e := getOriginPolicyReportDetail(sourceId) if e != nil { msg = "拉取英文策略报告详情失败" err = e return } if originDetail.IndustryId != 1 || originDetail.FieldId != 1 || originDetail.TypeId != 9 { // 类型不匹配,当前只获取英文策略报告 return } tmp := &tables.EnglishPolicyReport{ ClassifyIdFirst: originDetail.Industry.Id, ClassifyNameFirst: originDetail.Industry.Description, ClassifyIdSecond: originDetail.FieldId, ClassifyNameSecond: originDetail.Field.Description, Title: originDetail.TitleEn, Abstract: originDetail.Content.Abstract, Author: originDetail.Author.Name, Frequency: originDetail.Frequency, CreateTime: time.Now(), ModifyTime: time.Now(), State: 1, Content: originDetail.Content.Body, PublishStatus: originDetail.PublishStatus, PublishTime: originDetail.PublishDate, KeyTakeaways: originDetail.Content.Annotation, AuthorMobile: originDetail.AuthorPhoneNumber, SourceReportId: originDetail.Id, ReportCoverUrl: originDetail.Cover, } err = tables.AddEnglishPolicyReport(tmp) if err != nil { msg = "新增英文策略报告信息失败" return } //同步到英文研报 err, msg = EnglishPolicyReportSync(tmp.Id) return } func getOriginPolicyReportDetail(id int) (detail EnPolicyReportDataListItem, err error) { //设置接口地址 //处理返回值 url := utils.EnPolicyReportUrl + `articles/en/%d` url = fmt.Sprintf(url, id) utils.FileLog.Info("url:%s", url) body, err := http.Get(url) fmt.Println("getOriginPolicyReportDetail body:") fmt.Println(string(body)) item := new(EnPolicyReportDataDetailResp) err = json.Unmarshal(body, &item) if err != nil { return } if item.Code != 0 { err = fmt.Errorf("getOriginPolicyReportDetail ErrCode: %d, ErrMsg: %s", item.Code, item.Msg) return } detail = item.Data return } // EnglishPolicyReportSync 英文策略报告一键同步功能 func EnglishPolicyReportSync(id int) (err error, errMsg string) { //查询报告是否存在 policyReport, err := tables.GetEnglishPolicyReportById(id) if err != nil { if err.Error() == utils.ErrNoRow() { err = fmt.Errorf("报告不存在!") return } errMsg = "获取报告信息失败,Err:" + err.Error() err = fmt.Errorf("获取报告信息失败") return } //判断报告是否已同步 if policyReport.State == 2 { err = fmt.Errorf("报告已同步,无需重复同步") return } //新增英文研报 classifyNameFirst := "Equity" classifySecondName := "A-share Daily" // 根据分类名称查询分类ID classifyInfo, err := tables.GetEnglishClassifyByClassifyNameAndParentName(classifyNameFirst, classifySecondName) if err != nil { if err.Error() == utils.ErrNoRow() { err = fmt.Errorf("报告分类不存在!") return } errMsg = "获取报告分类失败,Err:" + err.Error() err = fmt.Errorf("获取报告分类失败") return } // 获取期数 maxStage, err := tables.GetEnglishReportStage(classifyInfo.ParentId, classifyInfo.Id) if err != nil { errMsg = "期数获取失败,Err:" + err.Error() err = fmt.Errorf("期数获取失败") return } var contentSub string if policyReport.Content != "" { contentSub, err = GetReportContentSub(policyReport.Content) if err != nil { go alarm_msg.SendAlarmMsg("策略报告 一键同步 ContentSub 失败,Err:"+err.Error(), 3) } } item := new(tables.EnglishReport) item.AddType = 1 item.ClassifyIdFirst = classifyInfo.ParentId item.ClassifyNameFirst = classifyInfo.ParentClassifyName item.ClassifyIdSecond = classifyInfo.Id item.ClassifyNameSecond = classifyInfo.ClassifyName item.Title = "China A-share Daily Check-in" item.Abstract = "China A-share market and economic data review" item.Author = "Horizon Insights FICC Team" item.Frequency = policyReport.Frequency item.State = 1 item.Content = policyReport.Content item.Stage = maxStage + 1 item.ContentSub = html.EscapeString(contentSub) item.CreateTime = time.Now().Format(utils.FormatDateTime) item.ModifyTime = time.Now() item.Overview = policyReport.Abstract item.KeyTakeaways = policyReport.KeyTakeaways item.FromReportId = policyReport.Id newReportId, err := tables.AddEnglishReport(item) if err != nil { errMsg = "保存研报失败,Err:" + err.Error() err = fmt.Errorf("保存研报失败") return } reportCode := utils.MD5(strconv.Itoa(int(newReportId))) //修改唯一编码 err = tables.ModifyEnglishReportCode(newReportId, reportCode) if err != nil { errMsg = "更新英文研报失败,Err:" + err.Error() err = fmt.Errorf("更新英文研报失败") return } //更新策略报告状态为已同步 if err = tables.SyncEnglishPolicyReportById(policyReport.Id, int(newReportId)); err != nil { errMsg = "更新策略报告失败,Err:" + err.Error() err = fmt.Errorf("更新策略报告失败") return } return } func GetReportContentSub(content string) (contentSub string, err error) { content = html.UnescapeString(content) doc, err := goquery.NewDocumentFromReader(strings.NewReader(content)) if err != nil { fmt.Println("create doc err:", err.Error()) return } n := 0 doc.Find("p").Each(func(i int, s *goquery.Selection) { if n >= 5 { return } n++ phtml, err := s.Html() if err != nil { fmt.Println("get html err", err.Error()) return } if s.Text() != "" || strings.Contains(phtml, "src") { contentSub = contentSub + "

" + phtml + "

" } }) return } type ApiDebugResponse struct { Code int `json:"code"` Msg string `json:"msg"` ErrMsg string `json:"err_msg"` } func TestDebugEnglishPolicyReport(id int) (err error) { url := fmt.Sprintf("http://8.136.199.33:8608/api/en/report/notify?id=%d", id) ret, err := http.Get(url) if err != nil { return } var resp ApiDebugResponse err = json.Unmarshal(ret, &resp) if err != nil { return } if resp.Code != 200 { err = errors.New(resp.Msg) return } return }