package xuexitong import ( "context" "encoding/json" "likedream-goframe/internal/application/xuexitong/entity" errors2 "likedream-goframe/internal/common/errors" "likedream-goframe/internal/framework/logger" "net/url" "strconv" "time" "github.com/avast/retry-go/v4" "go.uber.org/zap" ) // attachmentDetectDocument 从附件设置中检测并填充文档信息 func (c *XuexitongCourse) attachmentDetectDocument(attachment *entity.AttachmentSetting, p *entity.ChapterPoint) { for _, att := range attachment.Attachments { property, ok := att["property"].(map[string]interface{}) if !ok { continue } jobid, _ := property["jobid"].(string) if jobid != p.JobID && p.JobID != "" { continue } if name, ok := property["name"].(string); ok { p.Title = name } if bookname, ok := property["bookname"].(string); ok { p.Title = bookname } if jid, ok := property["jobid"].(string); ok { p.JobID = jid } if jtoken, ok := att["jtoken"].(string); ok { p.Jtoken = jtoken } if isJob, ok := att["job"].(bool); ok { p.IsJob = isJob } break } } // AttachmentsDetectionDocument 从附件设置中检测并填充文档信息 func (c *XuexitongCourse) AttachmentsDetectionDocument(attachment *entity.AttachmentSetting, p *entity.PointDocumentDto) error { if attachment == nil { return errors2.NewBusinessError(503, "附件设置为空") } for _, att := range attachment.Attachments { typeStr := "" if t, ok := att["type"].(string); ok { typeStr = t } else if property, ok := att["property"].(map[string]interface{}); ok { if module, ok := property["module"].(string); ok { typeStr = module } } property, ok := att["property"].(map[string]interface{}) if !ok { continue } jobid, _ := property["jobid"].(string) if jobid != p.JobID && p.JobID != "" { continue } if name, ok := property["name"].(string); ok { p.Title = name } if bookname, ok := property["bookname"].(string); ok { p.Title = bookname } if jid, ok := property["jobid"].(string); ok { p.JobID = jid } if jtoken, ok := att["jtoken"].(string); ok { p.Jtoken = jtoken } if isJob, ok := att["job"].(bool); ok { p.IsJob = isJob } if typeStr == "document" || typeStr == "insertdoc" { p.Type = "document" } else if typeStr == "insertbook" { p.Type = "insertbook" } break } return nil } // DocumentDtoReadingReport 提交文档阅读完成 func (c *XuexitongCourse) DocumentDtoReadingReport(ctx context.Context, p *entity.PointDocumentDto) (string, error) { params := url.Values{} params.Add("jobid", p.JobID) params.Add("knowledgeid", strconv.Itoa(p.KnowledgeID)) params.Add("courseid", p.CourseID) params.Add("clazzid", p.ClassID) params.Add("jtoken", p.Jtoken) params.Add("_dc", strconv.FormatInt(time.Now().UnixMilli(), 10)) apiUrl := ApiDocumentReport if p.Type == "insertbook" { apiUrl = ApiDocumentBook } var body string err := retry.Do(func() error { resp, err := c.client.R().SetHeaders(map[string]string{ "User-Agent": GetUA("mobile"), }).Get(apiUrl + "?" + params.Encode()) if err != nil { return err } if resp.StatusCode() != 200 { return errors2.NewBusinessError(resp.StatusCode(), "提交文档阅读失败") } body = resp.String() return nil }, retry.Attempts(3), retry.Delay(2*time.Second)) if err != nil { return "", err } return body, nil } // AutoReadDocument 自动阅读文档(刷课) func (c *XuexitongCourse) AutoReadDocument(ctx context.Context, course entity.XueXiTCourse, p *entity.PointDocumentDto) error { if !p.IsJob { logger.Logger.Info("文档不是任务点,跳过", zap.String("jobID", p.JobID), zap.String("title", p.Title)) return nil } logger.Logger.Info("开始刷文档", zap.String("jobID", p.JobID), zap.String("title", p.Title)) report, err := c.DocumentDtoReadingReport(ctx, p) if err != nil { return err } var result map[string]interface{} if err := json.Unmarshal([]byte(report), &result); err == nil { if status, ok := result["status"].(bool); ok && status { logger.Logger.Info("文档刷课完成", zap.String("jobID", p.JobID), zap.String("title", p.Title)) c.onTaskComplete() return nil } if msg, ok := result["msg"].(string); ok { logger.Logger.Warn("文档无法正常学习", zap.String("msg", msg)) } } return nil } // AutoReadDocumentByPoint 自动阅读文档(使用统一的 ChapterPoint) func (c *XuexitongCourse) AutoReadDocumentByPoint(ctx context.Context, course entity.XueXiTCourse, p *entity.ChapterPoint) error { if !p.IsJob { logger.Logger.Info("文档不是任务点,跳过", zap.String("jobID", p.JobID), zap.String("title", p.Title)) return nil } logger.Logger.Info("开始刷文档", zap.String("jobID", p.JobID), zap.String("title", p.Title)) report, err := c.DocumentDtoReadingReportByPoint(ctx, p) if err != nil { return err } var result map[string]interface{} if err := json.Unmarshal([]byte(report), &result); err == nil { if status, ok := result["status"].(bool); ok && status { logger.Logger.Info("文档刷课完成", zap.String("jobID", p.JobID), zap.String("title", p.Title)) c.onTaskComplete() return nil } if msg, ok := result["msg"].(string); ok { logger.Logger.Warn("文档无法正常学习", zap.String("msg", msg)) } } return nil } // DocumentDtoReadingReportByPoint 提交文档阅读完成(使用统一的 ChapterPoint) func (c *XuexitongCourse) DocumentDtoReadingReportByPoint(ctx context.Context, p *entity.ChapterPoint) (string, error) { params := url.Values{} params.Add("jobid", p.JobID) params.Add("knowledgeid", strconv.Itoa(p.KnowledgeID)) params.Add("courseid", p.CourseID) params.Add("clazzid", p.ClassID) params.Add("jtoken", p.Jtoken) params.Add("_dc", strconv.FormatInt(time.Now().UnixMilli(), 10)) apiUrl := ApiDocumentReport if p.DocumentType == "insertbook" { apiUrl = ApiDocumentBook } var body string err := retry.Do(func() error { resp, err := c.client.R().SetHeaders(map[string]string{ "User-Agent": GetUA("mobile"), }).Get(apiUrl + "?" + params.Encode()) if err != nil { return err } if resp.StatusCode() != 200 { return errors2.NewBusinessError(resp.StatusCode(), "提交文档阅读失败") } body = resp.String() return nil }, retry.Attempts(3), retry.Delay(2*time.Second)) if err != nil { return "", err } return body, nil }