feat(grpc): add support for fetching grades and exams
All checks were successful
Build / build (push) Successful in 2m14s
All checks were successful
Build / build (push) Successful in 2m14s
Implement new gRPC task handlers for retrieving student grades and exam schedules. This includes adding new parser logic for processing score and exam data, and updating the client capabilities to advertise support for these new task types. - Add `getGrades` and `getExams` handlers in `grpc/handler.go` - Add `parser/encoding.go`, `parser/exam.go`, and `parser/score.go` for data parsing - Update `grpc/client.go` to include `TASK_TYPE_GET_GRADES` and `TASK_TYPE_GET_EXAMS` in capabilities
This commit is contained in:
128
parser/exam.go
Normal file
128
parser/exam.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"schedule_converter/client"
|
||||
"schedule_converter/config"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
)
|
||||
|
||||
type ExamType string
|
||||
|
||||
const (
|
||||
ExamTypeFinal ExamType = "final"
|
||||
ExamTypeMidterm ExamType = "midterm"
|
||||
ExamTypeMakeup ExamType = "makeup"
|
||||
)
|
||||
|
||||
type ExamEntry struct {
|
||||
Course string
|
||||
Date string
|
||||
Time string
|
||||
Week string
|
||||
Weekday string
|
||||
Type ExamType
|
||||
}
|
||||
|
||||
func examTypeToCode(t ExamType) string {
|
||||
switch t {
|
||||
case ExamTypeMidterm:
|
||||
return "02"
|
||||
case ExamTypeMakeup:
|
||||
return "03"
|
||||
default:
|
||||
return "01"
|
||||
}
|
||||
}
|
||||
|
||||
func FetchExams(httpClient *http.Client, examType ExamType) ([]ExamEntry, error) {
|
||||
examURL := config.BaseURL + "/kscx/queryKsForXs"
|
||||
fmt.Printf("[考试] 正在获取考试时间数据 (%s)...\n", examType)
|
||||
|
||||
data := fmt.Sprintf("xnxq=&kssjd=%s", examTypeToCode(examType))
|
||||
req, err := http.NewRequest("POST", examURL, strings.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header = client.GetHeadersWithContentType("application/x-www-form-urlencoded")
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
html, err := decodeResponseBody(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
exams, err := ParseExamTimeHTML(html, examType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("[考试] 共获取 %d 条考试记录 (%s)\n", len(exams), examType)
|
||||
return exams, nil
|
||||
}
|
||||
|
||||
func FetchAllExams(httpClient *http.Client) ([]ExamEntry, error) {
|
||||
var allExams []ExamEntry
|
||||
for _, et := range []ExamType{ExamTypeFinal, ExamTypeMidterm, ExamTypeMakeup} {
|
||||
exams, err := FetchExams(httpClient, et)
|
||||
if err != nil {
|
||||
fmt.Printf("[考试] 获取%s考试失败: %v\n", et, err)
|
||||
continue
|
||||
}
|
||||
allExams = append(allExams, exams...)
|
||||
}
|
||||
return allExams, nil
|
||||
}
|
||||
|
||||
func ParseExamTimeHTML(html string, examType ExamType) ([]ExamEntry, error) {
|
||||
doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var exams []ExamEntry
|
||||
|
||||
doc.Find("table.bot_line").Each(func(_ int, table *goquery.Selection) {
|
||||
rows := table.Find("tr")
|
||||
if rows.Length() < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
rows.Each(func(idx int, row *goquery.Selection) {
|
||||
if idx == 0 {
|
||||
return
|
||||
}
|
||||
cells := row.Find("td")
|
||||
if cells.Length() < 6 {
|
||||
return
|
||||
}
|
||||
|
||||
texts := getCellTexts(cells)
|
||||
|
||||
exam := ExamEntry{
|
||||
Course: safeGet(texts, 1),
|
||||
Date: safeGet(texts, 2),
|
||||
Time: safeGet(texts, 3),
|
||||
Week: safeGet(texts, 4),
|
||||
Weekday: safeGet(texts, 5),
|
||||
Type: examType,
|
||||
}
|
||||
|
||||
if exam.Course != "" && len(exam.Course) >= 2 {
|
||||
exams = append(exams, exam)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return exams, nil
|
||||
}
|
||||
Reference in New Issue
Block a user