186 lines
6.9 KiB
Go
186 lines
6.9 KiB
Go
package sc
|
|
|
|
import (
|
|
"context"
|
|
"likedream-goframe/internal/application/smartedu/model"
|
|
"likedream-goframe/internal/common/errors"
|
|
"likedream-goframe/internal/framework/logger"
|
|
"likedream-goframe/internal/utils"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/samber/oops"
|
|
"github.com/tidwall/gjson"
|
|
"go.uber.org/zap"
|
|
"resty.dev/v3"
|
|
)
|
|
|
|
const (
|
|
HomeUrl = "https://basic.sc.smartedu.cn/hd/teacherTraining/home"
|
|
CourseDetailUrl = "https://basic.sc.smartedu.cn/hd/teacherTraining/api/studyCourse/getCourseDetails"
|
|
RecordProcessUrl = "https://basic.sc.smartedu.cn/hd/teacherTraining/api/studyCourseUser/recordProcess"
|
|
RefresProcessUrl = "https://basic.sc.smartedu.cn/hd/teacherTraining/api/studyCourseUser/refreshProcess"
|
|
ApiCourseFinishedHour = "https://basic.sc.smartedu.cn/hd/teacherTraining/api/studyCourse/getCourseFinishedHour"
|
|
)
|
|
|
|
type Course struct {
|
|
Client *resty.Client
|
|
Token string
|
|
}
|
|
|
|
func NewCourse(token string, client *resty.Client) *Course {
|
|
return &Course{
|
|
Token: token,
|
|
Client: client,
|
|
}
|
|
}
|
|
|
|
func (c *Course) GetCourseList(ctx context.Context) []model.Course {
|
|
jsUrl := c.GetJsUrl(ctx, HomeUrl)
|
|
get, err := c.Client.R().Get(jsUrl)
|
|
utils.OkOrPanic(err, oops.WithContext(ctx).With("jsUrl", jsUrl).Wrap)
|
|
jsonString := ParseJsonString(get.String())
|
|
returnData := gjson.Get(jsonString, "returnData").Array()
|
|
var courseList []model.Course
|
|
for _, one := range returnData {
|
|
courseList = append(courseList, model.Course{
|
|
Id: one.Get("id").String(),
|
|
CourseName: one.Get("courseName").String(),
|
|
Image: one.Get("studyFiles.filePath").String(),
|
|
})
|
|
}
|
|
return courseList
|
|
}
|
|
|
|
func (c *Course) GetChapterList(ctx context.Context, courseId string) []model.Chapter {
|
|
get, err := c.Client.R().SetQueryParam("courseId", courseId).SetHeader("X-Token", c.Token).Get(CourseDetailUrl)
|
|
utils.OkOrPanic(err, oops.WithContext(ctx).With("GetChapterList", courseId).Wrap)
|
|
chapterJson := gjson.Get(get.String(), "returnData.chapters").Array()
|
|
var chapterList []model.Chapter
|
|
for _, ch := range chapterJson {
|
|
chapter := model.Chapter{
|
|
Id: ch.Get("id").String(),
|
|
ChapterName: ch.Get("chapterName").String(),
|
|
}
|
|
subSectionJson := ch.Get("studySubsections").Array()
|
|
var subSectionList []model.SubSection
|
|
for _, sec := range subSectionJson {
|
|
studyFileJson := sec.Get("studyFiles")
|
|
studyFile := model.StudyFile{
|
|
Id: studyFileJson.Get("id").String(),
|
|
FileName: studyFileJson.Get("fileName").String(),
|
|
FileSize: studyFileJson.Get("fileSize").String(),
|
|
FileTime: studyFileJson.Get("fileTime").String(),
|
|
FileType: studyFileJson.Get("fileType").String(),
|
|
FilePath: studyFileJson.Get("filePath").String(),
|
|
VideoTime: studyFileJson.Get("videoTime").String(),
|
|
State: studyFileJson.Get("state").String(),
|
|
StudyTime: studyFileJson.Get("studyTime").String(),
|
|
}
|
|
subSection := model.SubSection{
|
|
Id: sec.Get("id").String(),
|
|
SubsectionName: sec.Get("subsectionName").String(),
|
|
VideoTime: sec.Get("videoTime").String(),
|
|
StudyFiles: studyFile,
|
|
}
|
|
|
|
subSectionList = append(subSectionList, subSection)
|
|
}
|
|
chapter.SubSection = subSectionList
|
|
chapterList = append(chapterList, chapter)
|
|
}
|
|
|
|
return chapterList
|
|
}
|
|
|
|
func ParseJsonString(str string) string {
|
|
// eval("module.exports = /*#__PURE__*/JSON.parse('{...}');\n\n//# sourceURL=...
|
|
re := regexp.MustCompile(`#__PURE__\*/JSON\.parse\('(.+?)'\);`)
|
|
matches := re.FindStringSubmatch(str)
|
|
if len(matches) < 2 {
|
|
return ""
|
|
}
|
|
// 处理转义的引号
|
|
return strings.ReplaceAll(matches[1], `\"`, `"`)
|
|
}
|
|
|
|
func (c *Course) GetJsUrl(ctx context.Context, url string) string {
|
|
get, err := c.Client.R().Get(url)
|
|
utils.OkOrPanic(err, oops.WithContext(ctx).With("GetJsUrl", url).Wrap)
|
|
return ParseJsUrl(get.String())
|
|
}
|
|
|
|
func (c *Course) Study(ctx context.Context, c2 model.Course, ch model.Chapter, sec model.SubSection) {
|
|
// 如果已完成
|
|
if sec.StudyFiles.State == "3" {
|
|
return
|
|
}
|
|
|
|
form := map[string]any{
|
|
"chapterId": ch.Id,
|
|
"courseId": c2.Id,
|
|
"subsectionId": sec.Id,
|
|
}
|
|
if sec.StudyFiles.State == "1" {
|
|
form["state"] = "1"
|
|
c.Refresh(ctx, c2, ch, sec)
|
|
form["studyTime"] = 5
|
|
// 如果state为
|
|
post, err := c.Client.R().SetHeader("X-Token", c.Token).SetBody(form).Post(RecordProcessUrl)
|
|
utils.OkOrPanic(err, oops.WithContext(ctx).With("Study", form).Wrap)
|
|
str := post.String()
|
|
if gjson.Get(str, "returnCode").String() != "200" {
|
|
utils.OkOrPanic(errors.NewBusinessError(503, "学习失败,"+gjson.Get(str, "returnMessage").String()))
|
|
}
|
|
logger.Logger.Info("学习成功", zap.String("课程名", c2.CourseName), zap.String("章节名", ch.ChapterName), zap.String("小节名", sec.SubsectionName))
|
|
}
|
|
c.Refresh(ctx, c2, ch, sec)
|
|
atoi, _ := strconv.Atoi(sec.StudyFiles.VideoTime)
|
|
form["state"] = "3"
|
|
form["studyTime"] = atoi
|
|
// 如果state为
|
|
post, err := c.Client.R().SetHeader("X-Token", c.Token).SetBody(form).Post(RecordProcessUrl)
|
|
utils.OkOrPanic(err, oops.WithContext(ctx).With("Study", form).Wrap)
|
|
str := post.String()
|
|
if gjson.Get(str, "returnCode").String() != "200" {
|
|
utils.OkOrPanic(errors.NewBusinessError(503, "学习失败,"+gjson.Get(str, "returnMessage").String()))
|
|
}
|
|
logger.Logger.Info("学习成功", zap.String("课程名", c2.CourseName), zap.String("章节名", ch.ChapterName), zap.String("小节名", sec.SubsectionName))
|
|
}
|
|
|
|
func (c *Course) Refresh(ctx context.Context, c2 model.Course, ch model.Chapter, sec model.SubSection) {
|
|
form := map[string]any{
|
|
"chapterId": ch.Id,
|
|
"courseId": c2.Id,
|
|
"subsectionId": sec.Id,
|
|
"studyTime": 0,
|
|
}
|
|
post, err := c.Client.R().SetHeader("X-Token", c.Token).SetBody(form).Post(RefresProcessUrl)
|
|
utils.OkOrPanic(err, oops.WithContext(ctx).With("Refresh", form).Wrap)
|
|
str := post.String()
|
|
if gjson.Get(str, "returnCode").String() != "200" {
|
|
utils.OkOrPanic(errors.NewBusinessError(503, "刷新嫉妒失败,"+gjson.Get(str, "returnMessage").String()))
|
|
}
|
|
logger.Logger.Info("刷新成功", zap.String("课程名", c2.CourseName), zap.String("章节名", ch.ChapterName), zap.String("小节名", sec.SubsectionName))
|
|
}
|
|
|
|
func ParseJsUrl(str string) string {
|
|
// <script defer src="https://cdnbasic.scbdc.edu.cn/%E7%9C%81%E7%BA%A7%E8%B5%84%E6%BA%90/hd/chunk-vendors.5e79f5ce155849.js">
|
|
re := regexp.MustCompile(`https://[^"'\s]+chunk-vendors[^"'\s]+\.js`)
|
|
match := re.FindString(str)
|
|
if match == "" {
|
|
return ""
|
|
}
|
|
return strings.Replace(match, "chunk-vendors", "src_views_home_index_vue", 1)
|
|
}
|
|
func (c *Course) GetCourseProcees(ctx context.Context, courseId string) (finished string, total string) {
|
|
post, err := c.Client.R().SetHeader("X-Token", c.Token).SetBody(map[string]any{
|
|
"courseIds": []string{courseId},
|
|
}).Post(ApiCourseFinishedHour)
|
|
utils.OkOrPanic(err, oops.WithContext(ctx).With("GetCourseProcees", courseId).Wrap)
|
|
str := gjson.Get(post.String(), "returnData.finishedHours").String()
|
|
split := strings.Split(str, ",")
|
|
return split[0], split[1]
|
|
}
|