package xuexitong import ( "context" "encoding/json" "fmt" "likedream-goframe/internal/application/xuexitong/entity" errors2 "likedream-goframe/internal/common/errors" "likedream-goframe/internal/framework/logger" "time" "github.com/avast/retry-go/v4" "go.uber.org/zap" ) // attachmentDetectHyperlink 从附件设置中检测并填充外链信息 func (c *XuexitongCourse) attachmentDetectHyperlink(attachment *entity.AttachmentSetting, p *entity.ChapterPoint) { for _, att := range attachment.Attachments { jobid, _ := att["jobid"].(string) if jobid != p.JobID { continue } property, ok := att["property"].(map[string]interface{}) if !ok { continue } if title, ok := property["title"].(string); ok { p.Title = title } if jtoken, ok := att["jtoken"].(string); ok { p.Jtoken = jtoken } if isJob, ok := att["job"].(bool); ok { p.IsJob = isJob } break } } // AttachmentsDetectionHyperlink 从附件设置中检测并填充外链信息 func (c *XuexitongCourse) AttachmentsDetectionHyperlink(attachment *entity.AttachmentSetting, p *entity.PointHyperlinkDto) error { if attachment == nil { return errors2.NewBusinessError(503, "附件设置为空") } for _, att := range attachment.Attachments { jobid, _ := att["jobid"].(string) if jobid != p.JobID { continue } property, ok := att["property"].(map[string]interface{}) if !ok { continue } if title, ok := property["title"].(string); ok { p.Title = title } if jtoken, ok := att["jtoken"].(string); ok { p.Jtoken = jtoken } if isJob, ok := att["job"].(bool); ok { p.IsJob = isJob } break } return nil } // AutoCompleteHyperlink 自动完成外链任务点 func (c *XuexitongCourse) AutoCompleteHyperlink(ctx context.Context, course entity.XueXiTCourse, p *entity.PointHyperlinkDto) 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.HyperlinkDtoCompleteReport(ctx, p) if err != nil { return fmt.Errorf("提交外链完成失败: %w", 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 } // AutoCompleteHyperlinkByPoint 自动完成外链任务点(使用统一的 ChapterPoint) func (c *XuexitongCourse) AutoCompleteHyperlinkByPoint(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.HyperlinkDtoCompleteReportByPoint(ctx, p) if err != nil { return fmt.Errorf("提交外链完成失败: %w", 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 } // HyperlinkDtoCompleteReport 提交外链完成 func (c *XuexitongCourse) HyperlinkDtoCompleteReport(ctx context.Context, p *entity.PointHyperlinkDto) (string, error) { urlStr := fmt.Sprintf("https://mooc1.chaoxing.com/ananas/job/hyperlink?jobid=%s&knowledgeid=%d&courseid=%s&clazzid=%s&jtoken=%s&checkMicroTopic=trueµTopicId=undefined&_dc=%d", p.JobID, p.KnowledgeID, p.CourseID, p.ClassID, p.Jtoken, time.Now().UnixMilli()) var body string err := retry.Do(func() error { resp, err := c.client.R().SetHeaders(map[string]string{ "User-Agent": GetUA("web"), }).Get(urlStr) 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 } // HyperlinkDtoCompleteReportByPoint 提交外链完成(使用统一的 ChapterPoint) func (c *XuexitongCourse) HyperlinkDtoCompleteReportByPoint(ctx context.Context, p *entity.ChapterPoint) (string, error) { urlStr := fmt.Sprintf("https://mooc1.chaoxing.com/ananas/job/hyperlink?jobid=%s&knowledgeid=%d&courseid=%s&clazzid=%s&jtoken=%s&checkMicroTopic=trueµTopicId=undefined&_dc=%d", p.JobID, p.KnowledgeID, p.CourseID, p.ClassID, p.Jtoken, time.Now().UnixMilli()) var body string err := retry.Do(func() error { resp, err := c.client.R().SetHeaders(map[string]string{ "User-Agent": GetUA("web"), }).Get(urlStr) 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 }