增加代码注释,修复答题翻页

This commit is contained in:
johlanse 2022-08-01 17:51:45 +08:00
parent 2d120bcf32
commit 7dd67cee7e
9 changed files with 282 additions and 31 deletions

1
dist/qrcode.js vendored Normal file

File diff suppressed because one or more lines are too long

42
dist/scheme.html vendored Normal file
View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="qrcode.js"></script>
<style>
.wx{
font-size: 30px;
color: red;
}
</style>
</head>
<body>
<div>
<button><a id="login" href="#"><h1>点击登录跳转学习强国app</h1></a></button>
</div>
<div id="wx" class="wx"></div>
<div id="qrcode" style="margin-top: 10px">
<img id="img" src="#" alt="#"/>
</div>
</body>
<script>
function load() {
if (isWechat()){
document.getElementById("wx").innerText = "当前为微信环境,请点击右上角浏览器中打开"
}
let search = window.location.search
search = search.substring(1,search.length)
document.getElementById("login").setAttribute("href","dtxuexi://appclient/page/study_feeds?url="+search)
console.log(unescape(search))
let imgBase64 = jrQrcode.getQrBase64(unescape(search), {});
document.getElementById("img").setAttribute("src",imgBase64)
document.getElementById("login").click()
}
function isWechat() {
return /MicroMessenger/i.test(window.navigator.userAgent);
}
load()
</script>
</html>

View File

@ -1,13 +1,20 @@
package lib package lib
import ( import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
rand2 "math/rand" rand2 "math/rand"
"net/http"
"regexp" "regexp"
"strings" "strings"
"time" "time"
"github.com/imroc/req/v3"
"github.com/mxschmitt/playwright-go" "github.com/mxschmitt/playwright-go"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
"github.com/huoxue1/study_xxqg/model" "github.com/huoxue1/study_xxqg/model"
) )
@ -23,6 +30,12 @@ div:nth-child(7) > div.my-points-card-footer > div.buttonbox > div`
div > div.my-points-section > div.my-points-content > div:nth-child(6) > div.my-points-card-footer > div.buttonbox > div` div > div.my-points-section > div.my-points-content > div:nth-child(6) > div.my-points-card-footer > div.buttonbox > div`
) )
// RespondDaily
/* @Description:
* @receiver c
* @param user
* @param model
*/
func (c *Core) RespondDaily(user *model.User, model string) { func (c *Core) RespondDaily(user *model.User, model string) {
defer func() { defer func() {
err := recover() err := recover()
@ -110,9 +123,22 @@ func (c *Core) RespondDaily(user *model.User, model string) {
return return
} }
err = page.Click(WEEKEND) // err = page.Click(WEEKEND)
// if err != nil {
// log.Errorln("跳转到积分页面错误")
// return
//}
id, err := getweekID(user.ToCookies())
if err != nil { if err != nil {
log.Errorln("跳转到积分页面错误") return
}
_, err = page.Goto(fmt.Sprintf("https://pc.xuexi.cn/points/exam-weekly-detail.html?id=%d", id), playwright.PageGotoOptions{
Referer: playwright.String(MyPointsUri),
Timeout: playwright.Float(10000),
WaitUntil: playwright.WaitUntilStateDomcontentloaded,
})
if err != nil {
log.Errorln("跳转到答题页面错误" + err.Error())
return return
} }
c.Push("text", "已加载每周答题模块") c.Push("text", "已加载每周答题模块")
@ -125,10 +151,23 @@ func (c *Core) RespondDaily(user *model.User, model string) {
return return
} }
err = page.Click(SPECIALBUTTON) // err = page.Click(SPECIALBUTTON)
// if err != nil {
// log.Errorln("跳转到积分页面错误")
//
// return
//}
id, err := getSpecialID(user.ToCookies())
if err != nil { if err != nil {
log.Errorln("跳转到积分页面错误") return
}
_, err = page.Goto(fmt.Sprintf("https://pc.xuexi.cn/points/exam-paper-detail.html?id=%d", id), playwright.PageGotoOptions{
Referer: playwright.String(MyPointsUri),
Timeout: playwright.Float(10000),
WaitUntil: playwright.WaitUntilStateDomcontentloaded,
})
if err != nil {
log.Errorln("跳转到答题页面错误" + err.Error())
return return
} }
c.Push("text", "已加载专项答题模块") c.Push("text", "已加载专项答题模块")
@ -136,9 +175,9 @@ func (c *Core) RespondDaily(user *model.User, model string) {
} }
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
// 跳转到答题页面若返回true则说明已答完 // 跳转到答题页面若返回true则说明已答完
if getAnswerPage(page, model) { // if getAnswerPage(page, model) {
return // return
} //}
tryCount := 0 tryCount := 0
for true { for true {
@ -595,3 +634,75 @@ func RemoveRepByLoop(slc []string) []string {
} }
return result return result
} }
func getSpecialID(cookies []*http.Cookie) (int, error) {
c := req.C()
c.SetCommonCookies(cookies...)
repo, err := c.R().SetQueryParams(map[string]string{"pageSize": "1000", "pageNo": "1"}).Get(querySpecialList)
if err != nil {
log.Errorln("获取专项答题列表错误" + err.Error())
return 0, err
}
dataB64, err := repo.ToString()
if err != nil {
log.Errorln("获取专项答题列表获取string错误" + err.Error())
return 0, err
}
data, err := base64.StdEncoding.DecodeString(gjson.Get(dataB64, "data_str").String())
if err != nil {
log.Errorln("获取专项答题列表转换b64错误" + err.Error())
return 0, err
}
list := new(SpecialList)
err = json.Unmarshal(data, list)
if err != nil {
log.Errorln("获取专项答题列表转换json错误" + err.Error())
return 0, err
}
log.Infoln(fmt.Sprintf("共获取到专项答题%d个", list.TotalCount))
for _, s := range list.List {
if s.TipScore == 0 {
log.Infoln(fmt.Sprintf("获取到未答专项答题: %vid: %v", s.Name, s.Id))
return s.Id, nil
}
}
log.Warningln("你已不存在未答的专项答题了")
return 0, errors.New("未找到专项答题")
}
func getweekID(cookies []*http.Cookie) (int, error) {
c := req.C()
c.SetCommonCookies(cookies...)
repo, err := c.R().SetQueryParams(map[string]string{"pageSize": "500", "pageNo": "1"}).Get(queryWeekList)
if err != nil {
log.Errorln("获取每周答题列表错误" + err.Error())
return 0, err
}
dataB64, err := repo.ToString()
if err != nil {
log.Errorln("获取每周答题列表获取string错误" + err.Error())
return 0, err
}
data, err := base64.StdEncoding.DecodeString(gjson.Get(dataB64, "data_str").String())
if err != nil {
log.Errorln("获取每周答题列表转换b64错误" + err.Error())
return 0, err
}
list := new(WeekList)
err = json.Unmarshal(data, list)
if err != nil {
log.Errorln("获取每周答题列表转换json错误" + err.Error())
return 0, err
}
log.Infoln(fmt.Sprintf("共获取到每周答题%d个", list.TotalCount))
for _, s := range list.List {
for _, practice := range s.Practices {
if practice.TipScore == 0 {
log.Infoln(fmt.Sprintf("获取到未答每周答题: %vid: %v", practice.Name, practice.Id))
return practice.Id, nil
}
}
}
log.Warningln("你已不存在未答的每周答题了")
return 0, errors.New("未找到每周答题")
}

View File

@ -26,7 +26,7 @@ func GetUserScore(cookies []*http.Cookie) (Score, error) {
var score Score var score Score
var resp []byte var resp []byte
// 获取用户总分 // 获取用户总分
err := gout.GET(user_totalScore_url).SetCookies(cookies...).SetHeader(gout.H{ err := gout.GET(userTotalscoreUrl).SetCookies(cookies...).SetHeader(gout.H{
"Cache-Control": "no-cache", "Cache-Control": "no-cache",
}).BindBody(&resp).Do() }).BindBody(&resp).Do()
if err != nil { if err != nil {
@ -43,7 +43,7 @@ func GetUserScore(cookies []*http.Cookie) (Score, error) {
score.TotalScore = int(gjson.GetBytes(resp, "data.score").Int()) score.TotalScore = int(gjson.GetBytes(resp, "data.score").Int())
// 获取用户今日得分 // 获取用户今日得分
err = gout.GET(user_todayTotalScore_url).SetCookies(cookies...).SetHeader(gout.H{ err = gout.GET(userTodaytotalscoreUrl).SetCookies(cookies...).SetHeader(gout.H{
"Cache-Control": "no-cache", "Cache-Control": "no-cache",
}).BindBody(&resp).Do() }).BindBody(&resp).Do()
if err != nil { if err != nil {
@ -54,7 +54,7 @@ func GetUserScore(cookies []*http.Cookie) (Score, error) {
// log.Debugln(gjson.GetBytes(resp, "@this|@pretty")) // log.Debugln(gjson.GetBytes(resp, "@this|@pretty"))
score.TodayScore = int(gjson.GetBytes(resp, "data.score").Int()) score.TodayScore = int(gjson.GetBytes(resp, "data.score").Int())
err = gout.GET(user_rateScore_url).SetCookies(cookies...).SetHeader(gout.H{ err = gout.GET(userRatescoreUrl).SetCookies(cookies...).SetHeader(gout.H{
"Cache-Control": "no-cache", "Cache-Control": "no-cache",
}).BindBody(&resp).Do() }).BindBody(&resp).Do()
if err != nil { if err != nil {

View File

@ -1,8 +1,79 @@
package lib package lib
const ( const (
user_Info_url = "https://pc-api.xuexi.cn/open/api/user/info" userInfoUrl = "https://pc-api.xuexi.cn/open/api/user/info"
user_totalScore_url = "https://pc-api.xuexi.cn/open/api/score/get" userTotalscoreUrl = "https://pc-api.xuexi.cn/open/api/score/get"
user_todayTotalScore_url = "https://pc-api.xuexi.cn/open/api/score/today/query" userTodaytotalscoreUrl = "https://pc-api.xuexi.cn/open/api/score/today/query"
user_rateScore_url = "https://pc-proxy-api.xuexi.cn/api/score/days/listScoreProgress?sence=score&deviceType=2" userRatescoreUrl = "https://pc-proxy-api.xuexi.cn/api/score/days/listScoreProgress?sence=score&deviceType=2"
// pageSize=1000&pageNo=1
querySpecialList = "https://pc-proxy-api.xuexi.cn/api/exam/service/paper/pc/list"
queryWeekList = "https://pc-proxy-api.xuexi.cn/api/exam/service/practice/pc/weekly/more"
) )
type SpecialList struct {
PageNo int `json:"pageNo"`
PageSize int `json:"pageSize"`
TotalPageCount int `json:"totalPageCount"`
TotalCount int `json:"totalCount"`
List []struct {
TipScore int `json:"tipScore"`
EndDate string `json:"endDate"`
Achievement struct {
Score int `json:"score"`
Total int `json:"total"`
Correct int `json:"correct"`
} `json:"achievement"`
Year int `json:"year"`
SeeSolution bool `json:"seeSolution"`
Score int `json:"score"`
ExamScoreId int `json:"examScoreId"`
UsedTime int `json:"usedTime"`
Overdue bool `json:"overdue"`
Month int `json:"month"`
Name string `json:"name"`
QuestionNum int `json:"questionNum"`
AlreadyAnswerNum int `json:"alreadyAnswerNum"`
StartTime string `json:"startTime"`
Id int `json:"id"`
ExamTime int `json:"examTime"`
Forever int `json:"forever"`
StartDate string `json:"startDate"`
Status int `json:"status"`
} `json:"list"`
PageNum int `json:"pageNum"`
}
type WeekList struct {
PageNo int `json:"pageNo"`
PageSize int `json:"pageSize"`
TotalPageCount int `json:"totalPageCount"`
TotalCount int `json:"totalCount"`
List []struct {
Month string `json:"month"`
Practices []struct {
SeeSolution bool `json:"seeSolution"`
TipScore int `json:"tipScore"`
ExamScoreId int `json:"examScoreId"`
Overdue bool `json:"overdue"`
Achievement struct {
Total int `json:"total"`
Correct int `json:"correct"`
} `json:"achievement"`
Name string `json:"name"`
BeginYear int `json:"beginYear"`
StartTime string `json:"startTime"`
Id int `json:"id"`
BeginMonth int `json:"beginMonth"`
Status int `json:"status"`
TipScoreReasonType int `json:"tipScoreReasonType"`
} `json:"practices"`
} `json:"list"`
PageNum int `json:"pageNum"`
}
/*
{"month":"5月","practices":[{"seeSolution":true,"tipScore":4,"examScoreId":-1,"overdue":false,"achievement":{"total":5,"correct":4},"name":"2022年5月第四周答题","beginYear":2022,"startTime":"2022-05-23 10:35:00","id":276,"beginMonth":5,"status":2,"tipScoreReasonType":0},{"seeSolution":true,"tipScore":4,"examScoreId":-1,"overdue":false,"achievement":{"total":5,"correct":4},"name":"2022年5月第三周答题","beginYear":2022,"startTime":"2022-05-16 09:00:00","id":275,"beginMonth":5,"status":2,"tipScoreReasonType":0},{"seeSolution":true,"tipScore":4,"examScoreId":-1,"overdue":false,"achievement":{"total":5,"correct":4},"name":"2022年5月第二周答题","beginYear":2022,"startTime":"2022-05-09 08:30:00","id":274,"beginMonth":5,"status":2,"tipScoreReasonType":0},{"seeSolution":true,"tipScore":5,"examScoreId":-1,"overdue":false,"achievement":{"total":5,"correct":5},"name":"2022年5月第一周答题","beginYear":2022,"startTime":"2022-05-02 08:30:00","id":273,"beginMonth":5,"status":2,"tipScoreReasonType":0}]}
*/

View File

@ -20,7 +20,7 @@ import (
*/ */
func GetUserInfo(cookies []*http.Cookie) (string, string, error) { func GetUserInfo(cookies []*http.Cookie) (string, string, error) {
var resp []byte var resp []byte
err := gout.GET(user_Info_url). err := gout.GET(userInfoUrl).
SetCookies(cookies...). SetCookies(cookies...).
SetHeader(gout.H{ SetHeader(gout.H{
"Cache-Control": "no-cache", "Cache-Control": "no-cache",

View File

@ -1,3 +1,5 @@
// Package utils
// @Description:
package utils package utils
import ( import (
@ -6,6 +8,11 @@ import (
"os" "os"
) )
// FileIsExist
/* @Description:
* @param path
* @return bool
*/
func FileIsExist(path string) bool { func FileIsExist(path string) bool {
_, err := os.Stat(path) _, err := os.Stat(path)
if err == nil { if err == nil {
@ -17,6 +24,11 @@ func FileIsExist(path string) bool {
return false return false
} }
// StrMd5
/* @Description:
* @param str
* @return retMd5
*/
func StrMd5(str string) (retMd5 string) { func StrMd5(str string) (retMd5 string) {
h := md5.New() h := md5.New()
h.Write([]byte(str)) h.Write([]byte(str))

View File

@ -1,3 +1,5 @@
// Package web
// @Description:
package web package web
import ( import (
@ -23,7 +25,11 @@ var (
state = sync.Map{} state = sync.Map{}
) )
func CheckToken() gin.HandlerFunc { // checkToken
/* @Description:
* @return gin.HandlerFunc
*/
func checkToken() gin.HandlerFunc {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
token := ctx.Param("token") token := ctx.Param("token")
config := conf.GetConfig() config := conf.GetConfig()
@ -48,7 +54,7 @@ func CheckToken() gin.HandlerFunc {
} }
} }
func Login() gin.HandlerFunc { func userLogin() gin.HandlerFunc {
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
type user struct { type user struct {
Account string `json:"account"` Account string `json:"account"`
@ -176,7 +182,7 @@ func getUsers() gin.HandlerFunc {
} }
} }
func Cors() gin.HandlerFunc { func cors() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
method := c.Request.Method method := c.Request.Method
origin := c.Request.Header.Get("Origin") // 请求头部 origin := c.Request.Header.Get("Origin") // 请求头部

View File

@ -1,3 +1,5 @@
// Package web
// @Description: 封装了所以web相关的内容
package web package web
import ( import (
@ -10,6 +12,7 @@ import (
"github.com/huoxue1/study_xxqg/utils" "github.com/huoxue1/study_xxqg/utils"
) )
// 将静态文件嵌入到可执行程序中来
//go:embed xxqg/build //go:embed xxqg/build
var static embed.FS var static embed.FS
@ -18,41 +21,46 @@ var static embed.FS
// @return *gin.Engine // @return *gin.Engine
func RouterInit() *gin.Engine { func RouterInit() *gin.Engine {
router := gin.Default() router := gin.Default()
router.Use(Cors()) router.Use(cors())
router.Group("/wx", func(context *gin.Context) {
})
// 挂载静态文件
router.StaticFS("/static", http.FS(static)) router.StaticFS("/static", http.FS(static))
// 访问首页时跳转到对应页面
router.GET("/", func(ctx *gin.Context) { router.GET("/", func(ctx *gin.Context) {
ctx.Redirect(301, "/static/xxqg/build/home.html") ctx.Redirect(301, "/static/xxqg/build/home.html")
}) })
// 对权限的管理组
auth := router.Group("/auth") auth := router.Group("/auth")
auth.POST("/login", Login()) // 用户登录的接口
auth.POST("/check/:token", CheckToken()) auth.POST("/login", userLogin())
// 检查登录状态的token是否正确
auth.POST("/check/:token", checkToken())
// 对于用户可自定义挂载文件的目录
if utils.FileIsExist("dist") { if utils.FileIsExist("dist") {
router.StaticFS("/dist", gin.Dir("./dist/", true)) router.StaticFS("/dist", gin.Dir("./dist/", true))
} }
// 对用户管理的组
user := router.Group("/user", check()) user := router.Group("/user", check())
// 添加用户 // 添加用户
user.POST("", addUser()) user.POST("", addUser())
// 获取所以已登陆的用户
user.GET("/", getUsers()) user.GET("/", getUsers())
// 删除用户
user.DELETE("/", deleteUser()) user.DELETE("/", deleteUser())
// 获取用户成绩
router.GET("/score", getScore()) router.GET("/score", getScore())
// 让一个用户开始学习
router.POST("/study", study()) router.POST("/study", study())
// 让一个用户停止学习
router.POST("/stop_study", check(), stopStudy()) router.POST("/stop_study", check(), stopStudy())
// 获取程序当天的运行日志
router.GET("/log", check(), getLog()) router.GET("/log", check(), getLog())
// 登录xxqg的三个接口
router.GET("/sign/*proxyPath", check(), sign()) router.GET("/sign/*proxyPath", check(), sign())
router.GET("/login/*proxyPath", check(), generate()) router.GET("/login/*proxyPath", check(), generate())
router.POST("/login/*proxyPath", check(), generate()) router.POST("/login/*proxyPath", check(), generate())