diff --git a/core/logrus.go b/core/logrus.go index d1461d5..a144d49 100644 --- a/core/logrus.go +++ b/core/logrus.go @@ -1,87 +1,3 @@ -//package core -// -//import ( -// "BronyaBot/global" -// "bytes" -// "fmt" -// "github.com/sirupsen/logrus" -// "os" -// "path" -//) -// -//const ( -// red = 31 -// yellow = 33 -// blue = 36 -// gray = 37 -//) -// -//type LogFormatter struct{} -// -//// Format 格式化日志 实现Formatter -//func (t LogFormatter) Format(entry *logrus.Entry) ([]byte, error) { -// //根据不同level展示颜色 -// var levelColor int -// switch entry.Level { -// case logrus.DebugLevel, logrus.TraceLevel: -// levelColor = gray -// case logrus.WarnLevel: -// levelColor = yellow -// case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel: -// levelColor = red -// default: -// levelColor = blue -// } -// var b *bytes.Buffer -// -// if entry.Buffer != nil { -// b = entry.Buffer -// } else { -// b = &bytes.Buffer{} -// } -// -// log := global.Config.Logger -// -// //自定义日期格式 -// timesTamp := entry.Time.Format("2006-01-02 15:04:05") -// if entry.HasCaller() { -// //自定义文件路径 -// funcVal := entry.Caller.Function -// fileVal := fmt.Sprintf("%s:%d", path.Base(entry.Caller.File), entry.Caller.Line) -// //自定义输出路径 -// _, _ = fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s %s %s\n", log.Prefix, timesTamp, levelColor, entry.Level, funcVal, fileVal, entry.Message) -// } else { -// _, _ = fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s\n", log.Prefix, timesTamp, levelColor, entry.Level, entry.Message) -// } -// return b.Bytes(), nil -//} -// -//func InitLogger() *logrus.Logger { -// mLog := logrus.New() //创建一个实例 -// mLog.SetOutput(os.Stdout) //设置输出类型 -// mLog.SetReportCaller(global.Config.Logger.ShowLine) //开启返回函数名 和 行号 -// mLog.SetFormatter(&LogFormatter{}) //设置自己定义的LogFormatter -// level, err := logrus.ParseLevel(global.Config.Logger.Level) -// if err != nil { -// level = logrus.InfoLevel -// } -// mLog.SetLevel(level) //设置最低的Level -// InitDefaultLogger() //调用全局log -// return mLog -//} -// -//func InitDefaultLogger() { -// //全局log -// logrus.SetOutput(os.Stdout) //设置输出类型 -// logrus.SetReportCaller(global.Config.Logger.ShowLine) -// logrus.SetFormatter(&LogFormatter{}) -// level, err := logrus.ParseLevel(global.Config.Logger.Level) -// if err != nil { -// level = logrus.InfoLevel -// } -// logrus.SetLevel(level) //设置最低的Level -//} - package core import ( @@ -104,9 +20,8 @@ const ( type LogFormatter struct{} -// Format 格式化日志 实现Formatter +// Format formats the log entry to include colored level indicators and caller information func (t LogFormatter) Format(entry *logrus.Entry) ([]byte, error) { - // 根据不同level展示颜色 var levelColor int switch entry.Level { case logrus.DebugLevel, logrus.TraceLevel: @@ -127,60 +42,40 @@ func (t LogFormatter) Format(entry *logrus.Entry) ([]byte, error) { } log := global.Config.Logger - - // 自定义日期格式 - timesTamp := entry.Time.Format("2006-01-02 15:04:05") + timeStamp := entry.Time.Format("2006-01-02 15:04:05") if entry.HasCaller() { - // 自定义文件路径 funcVal := entry.Caller.Function fileVal := fmt.Sprintf("%s:%d", path.Base(entry.Caller.File), entry.Caller.Line) - // 自定义输出路径 - _, _ = fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s %s %s\n", log.Prefix, timesTamp, levelColor, entry.Level, funcVal, fileVal, entry.Message) + _, _ = fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s %s %s\n", log.Prefix, timeStamp, levelColor, entry.Level, funcVal, fileVal, entry.Message) } else { - _, _ = fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s\n", log.Prefix, timesTamp, levelColor, entry.Level, entry.Message) + _, _ = fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s\n", log.Prefix, timeStamp, levelColor, entry.Level, entry.Message) } return b.Bytes(), nil } func InitLogger() *logrus.Logger { - mLog := logrus.New() // 创建一个实例 - mLog.SetOutput(os.Stdout) // 设置输出类型 - mLog.SetReportCaller(global.Config.Logger.ShowLine) // 开启返回函数名和行号 - mLog.SetFormatter(&LogFormatter{}) // 设置自定义的LogFormatter - + mLog := logrus.New() + mLog.SetOutput(os.Stdout) + mLog.SetReportCaller(global.Config.Logger.ShowLine) + mLog.SetFormatter(&LogFormatter{}) level, err := logrus.ParseLevel(global.Config.Logger.Level) if err != nil { level = logrus.InfoLevel } - mLog.SetLevel(level) // 设置最低的Level - - // 添加文件日志 - fileWriter := createLogFile() - if fileWriter != nil { - mLog.SetOutput(io.MultiWriter(os.Stdout, fileWriter)) - } - - InitDefaultLogger() // 调用全局log + mLog.SetLevel(level) + scheduleLogRotation(mLog) return mLog } -func InitDefaultLogger() { - // 全局log - logrus.SetOutput(os.Stdout) // 设置输出类型 - logrus.SetReportCaller(global.Config.Logger.ShowLine) - logrus.SetFormatter(&LogFormatter{}) - - level, err := logrus.ParseLevel(global.Config.Logger.Level) - if err != nil { - level = logrus.InfoLevel - } - logrus.SetLevel(level) // 设置最低的Level - - // 添加文件日志 - fileWriter := createLogFile() - if fileWriter != nil { - logrus.SetOutput(io.MultiWriter(os.Stdout, fileWriter)) - } +func scheduleLogRotation(logger *logrus.Logger) { + go func() { + for range time.NewTicker(24 * time.Hour).C { + fileWriter := createLogFile() + if fileWriter != nil { + logger.SetOutput(io.MultiWriter(os.Stdout, fileWriter)) + } + } + }() } func createLogFile() *os.File { diff --git a/internal/service/Init.go b/internal/service/Init.go index 3b47cce..d83506d 100644 --- a/internal/service/Init.go +++ b/internal/service/Init.go @@ -21,8 +21,13 @@ func NewAppService() *AppService { } func (svc *AppService) Init() { - svc.scheduleTasks() - svc.cron.Start() + //svc.scheduleTasks() + + //svc.cron.Start() + + //svc.StartTestCX() + svc.StartGongxueYun("sign") + //select {} } func (svc *AppService) scheduleTasks() { @@ -31,7 +36,6 @@ func (svc *AppService) scheduleTasks() { svc.addCronTask("0 8 * * *", "每天早上8点签到", "sign") svc.addCronTask("0 18 * * *", "每天晚上6点签到", "sign") svc.addCronTask("0 10 * * 5", "每周周五早上10点签到", "week") - svc.cron.AddFunc("0 10 ? * 1L", func() { if isLastWeek(time.Now()) { global.Log.Info("Running task: 每月最后一周的周一早上10点签到") diff --git a/internal/service/cx_service/data/ssologin_data.go b/internal/service/cx_service/data/ssologin_data.go new file mode 100644 index 0000000..840d7fc --- /dev/null +++ b/internal/service/cx_service/data/ssologin_data.go @@ -0,0 +1,119 @@ +package data + +type AccinfoData struct { + Msg struct { + Fid int `json:"fid"` + Rosterrights int `json:"rosterrights"` + CodeInfos struct { + HomeConfig struct { + Weburl string `json:"weburl"` + Dwtype int `json:"dwtype"` + Hometype int `json:"hometype"` + } `json:"homeConfig"` + } `json:"codeInfos"` + Boundaccount int `json:"boundaccount"` + LoginId int `json:"loginId"` + CodeInfo struct { + } `json:"codeInfo"` + Pic string `json:"pic"` + Source string `json:"source"` + Type int `json:"type"` + Ranknum string `json:"ranknum"` + IsCertify int `json:"isCertify"` + Uname string `json:"uname"` + CopyRight int `json:"copyRight"` + UnitConfig struct { + } `json:"unitConfig"` + Schoolname string `json:"schoolname"` + UnitConfigInfo struct { + HpConfig struct { + ShowBaseHp int `json:"showBaseHp"` + ShowMicroServiceHp int `json:"showMicroServiceHp"` + } `json:"hpConfig"` + Xb int `json:"xb"` + } `json:"unitConfigInfo"` + UnitConfigInfos []struct { + Fid int `json:"fid"` + HpConfig struct { + ShowBaseHp int `json:"showBaseHp"` + ShowMicroServiceHp int `json:"showMicroServiceHp"` + } `json:"hpConfig"` + Xb int `json:"xb"` + Schoolname string `json:"schoolname"` + } `json:"unitConfigInfos"` + Phone string `json:"phone"` + BindFanya bool `json:"bindFanya"` + UpdateWay string `json:"updateWay"` + Name string `json:"name"` + Fullpinyin string `json:"fullpinyin"` + UserConfig struct { + Recommend struct { + All int `json:"all"` + } `json:"recommend"` + } `json:"userConfig"` + Status int `json:"status"` + SwitchInfo string `json:"switchInfo"` + Roleid string `json:"roleid"` + Controlinfo struct { + InitializedRole string `json:"initializedRole"` + Selected string `json:"selected"` + } `json:"controlinfo"` + Industry int `json:"industry"` + Uid int `json:"uid"` + Acttime2 string `json:"acttime2"` + Dxfid string `json:"dxfid"` + Puid int `json:"puid"` + Rights int `json:"rights"` + NeedIntruction int `json:"needIntruction"` + Openid4 string `json:"openid4"` + BindOpac bool `json:"bindOpac"` + Ppfid string `json:"ppfid"` + AccountInfo struct { + CxOpac struct { + LoginId int `json:"loginId"` + Tiptitle string `json:"tiptitle"` + LoginUrl string `json:"loginUrl"` + BoundUrl string `json:"boundUrl"` + Tippwd string `json:"tippwd"` + Tipuname string `json:"tipuname"` + } `json:"cx_opac"` + ImAccount struct { + Uid int `json:"uid"` + Password string `json:"password"` + Created int64 `json:"created"` + Modified int64 `json:"modified"` + Type string `json:"type"` + Uuid string `json:"uuid"` + Activated int `json:"activated"` + Username string `json:"username"` + } `json:"imAccount"` + CxFanya struct { + LoginId int `json:"loginId"` + CopyRight int `json:"copyRight"` + Roleid string `json:"roleid"` + Countrycode string `json:"countrycode"` + Tippwd string `json:"tippwd"` + Result bool `json:"result"` + Uid int `json:"uid"` + Dxfid string `json:"dxfid"` + Tiptitle string `json:"tiptitle"` + LoginUrl string `json:"loginUrl"` + Schoolid int `json:"schoolid"` + Time int64 `json:"time"` + BoundUrl string `json:"boundUrl"` + Tipuname string `json:"tipuname"` + IsCertify int `json:"isCertify"` + Cxid int `json:"cxid"` + CreateDate string `json:"createDate"` + Status int `json:"status"` + } `json:"cx_fanya"` + } `json:"accountInfo"` + Simplepinyin string `json:"simplepinyin"` + Sex int `json:"sex"` + IsNewUser int `json:"isNewUser"` + Studentcode string `json:"studentcode"` + PrivacyPolicyVersion int `json:"privacyPolicyVersion"` + Inputfid int `json:"inputfid"` + } `json:"msg"` + Result int `json:"result"` +} diff --git a/internal/service/cx_service/logic.go b/internal/service/cx_service/logic.go index 060d0e8..dd0f1b9 100644 --- a/internal/service/cx_service/logic.go +++ b/internal/service/cx_service/logic.go @@ -6,29 +6,36 @@ import ( "BronyaBot/internal/service/cx_service/data" "BronyaBot/utils" "encoding/json" + "fmt" "io" "net/http" "net/url" + "strconv" "strings" ) -type CxLogic struct { - cookie string - Phone string - Password string +func (cx *CxLogic) loadAccount() { + cx.Phone = global.Config.Account.Cx.Phone + cx.Password = global.Config.Account.Cx.Password } - func (cx *CxLogic) Run() { + cx.loadAccount() global.Log.Info("Starting CX test module...") if err := cx.Login(); err != nil { global.Log.Error("CX login failed:", err) return } - cx.PullCourse() + if err := cx.accInfo(); err != nil { + global.Log.Error(err) + return + } + + if err := cx.PullCourse(); err != nil { + global.Log.Error(err) + } } func (c *CxLogic) Login() error { - global.Log.Info("=====开始登录=====") phone, _ := utils.AESCBCEncrypt([]byte(c.Phone)) password, _ := utils.AESCBCEncrypt([]byte(c.Password)) @@ -61,7 +68,31 @@ func (c *CxLogic) Login() error { } return nil } -func (c *CxLogic) PullCourse() { +func (c *CxLogic) accInfo() error { + accinfoData := &data.AccinfoData{} + resp, _ := http.NewRequest("GET", api.API_SSO_LOGIN, nil) + resp.Header.Add("Cookie", c.cookie) + resp.Header.Add("User-Agent", "Apifox/1.0.0 (https://apifox.com)") + res, _ := c.client.Do(resp) + defer res.Body.Close() + body, err := io.ReadAll(res.Body) + if err != nil { + global.Log.Error("CX login failed:", err) + } + err = json.Unmarshal(body, &accinfoData) + if err != nil { + global.Log.Error(err) + } + msg := accinfoData.Msg + c.OssAccInfo.Puid = strconv.Itoa(msg.Puid) + c.OssAccInfo.Phone = msg.Phone + c.OssAccInfo.Uname = msg.Uname + c.OssAccInfo.Name = msg.Name + c.OssAccInfo.Sex = strconv.Itoa(msg.Sex) + global.Log.Infof("账号登录成功: %s %s %s %s %s", c.OssAccInfo.Puid, c.OssAccInfo.Name, c.OssAccInfo.Sex, c.OssAccInfo.Phone, c.OssAccInfo.Uname) + return nil +} +func (c *CxLogic) PullCourse() error { global.Log.Info("=====拉取课程=====") client := &http.Client{} request, err := http.NewRequest("GET", api.API_CLASS_LST, nil) @@ -81,8 +112,24 @@ func (c *CxLogic) PullCourse() { global.Log.Error(err.Error()) } json.Unmarshal(body, &pull) - for i := range pull.ChannelList { - global.Log.Info(pull.ChannelList[i].Content) + if pull.Result != 1 { + return fmt.Errorf("拉取课程失败!") } + global.Log.Infof("拉取成功!共%d个课程", len(pull.ChannelList)) + for i, s := range pull.ChannelList { + global.Log.Infof("序号: %d 课程名: %s 老师名: %s 课程ID: %d 课程状态: %d - %s", i+1, s.Content.Course.Data[0].Name, s.Content.Course.Data[0].Teacherfactor, s.Content.Course.Data[0].Id, s.Content.Course.Data[0].Coursestate, + func() string { + switch s.Content.Course.Data[0].Coursestate { + case 0: + return "进行中" + case 1: + return "已结课" + default: + return "未知状态" + } + }()) + } + global.Log.Info("==========\n") + return nil } diff --git a/internal/service/cx_service/struct.go b/internal/service/cx_service/struct.go new file mode 100644 index 0000000..70c845b --- /dev/null +++ b/internal/service/cx_service/struct.go @@ -0,0 +1,18 @@ +package cx_service + +import "net/http" + +type CxLogic struct { + cookie string + Phone string + Password string + client http.Client + OssAccInfo oss_login +} +type oss_login struct { + Puid string `json:"puid"` + Name string `json:"name"` + Sex string `json:"sex"` + Phone string `json:"phone"` + Uname string `json:"uname"` +} diff --git a/internal/service/gongxueyun_service/logic.go b/internal/service/gongxueyun_service/logic.go index fb174f2..ad8b4be 100644 --- a/internal/service/gongxueyun_service/logic.go +++ b/internal/service/gongxueyun_service/logic.go @@ -26,11 +26,15 @@ func (m *MoguDing) Run(runType string) { global.Log.Error(err.Error()) return } - m.GetPlanId() - if err := m.GetJobInfo(); err != nil { + + if err := m.GetPlanId(); err != nil { global.Log.Error(err.Error()) return } + if err := m.GetJobInfo(); err != nil { + global.Log.Error("Failed to get job info: %v", err) + return + } m.getWeeksTime() if runType == "sign" { m.SignIn() @@ -52,15 +56,18 @@ var headers = map[string][]string{ var clientUid = strings.ReplaceAll(uuid.New().String(), "-", "") func addHeader(key, value string) { - // 检查 key 是否已经存在,若存在则追加到对应的值 if _, exists := headers[key]; exists { - //headers[key] = append(headers[key], value) headers[key] = []string{value} } else { - // 若不存在,则新建一个字段 headers[key] = []string{value} } } +func addStandardHeaders(roleKey, userId, authorization string) { + addHeader("rolekey", roleKey) + addHeader("userid", userId) + addHeader("authorization", authorization) + +} func (mo *MoguDing) GetBlock() error { global.Log.Infof("Starting sign-in process for user: %s", mo.Email) @@ -91,7 +98,6 @@ func (mo *MoguDing) processBlock() error { if err := json.Unmarshal(body, &blockData); err != nil { return fmt.Errorf("failed to parse block puzzle response: %v", err) } - // 初始化滑块验证码 captcha, err := blockPuzzle.NewSliderCaptcha(blockData.Data.JigsawImageBase64, blockData.Data.OriginalImageBase64) if err != nil { @@ -100,7 +106,6 @@ func (mo *MoguDing) processBlock() error { x, _ := captcha.FindBestMatch() // 加密并验证 - xY := map[string]string{"x": strconv.FormatFloat(GenerateRandomFloat(x), 'f', -1, 64), "y": strconv.Itoa(5)} global.Log.Info(fmt.Sprintf("Captcha matched at: xY=%s", xY)) @@ -169,10 +174,6 @@ func (mogu *MoguDing) Login() error { if err != nil { global.Log.Info(fmt.Sprintf("Failed to decrypt data: %v", err)) } - //if loginData.Phone == "" { - // mogu.Run() - // return nil - //} mogu.RoleKey = loginData.RoleKey mogu.UserId = loginData.UserId mogu.Authorization = loginData.Token @@ -183,13 +184,13 @@ func (mogu *MoguDing) Login() error { global.Log.Info("Login successful") return nil } -func (mogu *MoguDing) GetPlanId() { +func (mogu *MoguDing) GetPlanId() error { + defaultId := "6686304d065db846edab7d4565065abc" planData := &data.PlanByStuData{} timestamp, _ := EncryptTimestamp(time.Now().UnixMilli()) sign := utils.CreateSign(mogu.UserId, mogu.RoleKey) - addHeader("rolekey", mogu.RoleKey) addHeader("sign", sign) - addHeader("authorization", mogu.Authorization) + addStandardHeaders(mogu.RoleKey, mogu.UserId, mogu.Authorization) body := map[string]interface{}{ "pageSize": strconv.Itoa(999999), "t": timestamp, @@ -203,16 +204,18 @@ func (mogu *MoguDing) GetPlanId() { mogu.PlanID = planData.Data[i].PlanId mogu.PlanName = planData.Data[i].PlanName } + if strings.EqualFold(mogu.PlanID, defaultId) { + return fmt.Errorf(mogu.PlanName) + } global.Log.Info("================") global.Log.Info(mogu.PlanID) global.Log.Info(mogu.PlanName) global.Log.Info("================") + return nil } func (mogu *MoguDing) GetJobInfo() error { job := &data.JobInfoData{} - addHeader("rolekey", mogu.RoleKey) - addHeader("authorization", mogu.Authorization) - addHeader("userid", mogu.UserId) + addStandardHeaders(mogu.RoleKey, mogu.UserId, mogu.Authorization) timestamp, _ := EncryptTimestamp(time.Now().UnixMilli()) body := map[string]interface{}{ "planId": mogu.PlanID, @@ -236,9 +239,8 @@ func (mogu *MoguDing) SignIn() { resdata := &data.SaveData{} filling := DataStructureFilling(mogu) sign := utils.CreateSign(filling["device"].(string), filling["type"].(string), mogu.PlanID, mogu.UserId, filling["address"].(string)) - addHeader("rolekey", mogu.RoleKey) + addStandardHeaders(mogu.RoleKey, mogu.UserId, mogu.Authorization) addHeader("sign", sign) - addHeader("authorization", mogu.Authorization) request, err := utils.SendRequest("POST", api.BaseApi+api.SignAPI, filling, headers) if err != nil { global.Log.Info(fmt.Sprintf("Failed to send request: %v", err)) @@ -272,8 +274,7 @@ func (mogu *MoguDing) updateSignState(state int) { func (mogu *MoguDing) getSubmittedReportsInfo(reportType string) { report := &data.ReportsInfo{} sign := utils.CreateSign(mogu.UserId, mogu.RoleKey, reportType) - addHeader("rolekey", mogu.RoleKey) - addHeader("userid", mogu.UserId) + addStandardHeaders(mogu.RoleKey, mogu.UserId, mogu.Authorization) addHeader("sign", sign) timestamp, _ := EncryptTimestamp(time.Now().UnixMilli()) body := map[string]interface{}{ @@ -306,9 +307,7 @@ func (mogu *MoguDing) getSubmittedReportsInfo(reportType string) { // 获取提交周时间 func (mogu *MoguDing) getWeeksTime() { week := &data.WeeksData{} - addHeader("rolekey", mogu.RoleKey) - addHeader("authorization", mogu.Authorization) - addHeader("userid", mogu.UserId) + addStandardHeaders(mogu.RoleKey, mogu.UserId, mogu.Authorization) timestamp, _ := EncryptTimestamp(time.Now().UnixMilli()) body := map[string]interface{}{ "t": timestamp, @@ -318,11 +317,13 @@ func (mogu *MoguDing) getWeeksTime() { global.Log.Info(fmt.Sprintf("Failed to send request: %v", err)) } json.Unmarshal(request, &week) - mogu.WeekTime.Week = week.Data[0].Weeks - mogu.WeekTime.StartTime = week.Data[0].StartTime - mogu.WeekTime.EndTime = week.Data[0].EndTime - mogu.WeekTime.IsDefault = week.Data[0].IsDefault - mogu.WeekTime.Flag = week.Flag + if len(week.Data) > 0 { + mogu.WeekTime.Week = week.Data[0].Weeks + mogu.WeekTime.StartTime = week.Data[0].StartTime + mogu.WeekTime.EndTime = week.Data[0].EndTime + mogu.WeekTime.IsDefault = week.Data[0].IsDefault + mogu.WeekTime.Flag = week.Flag + } } // SubmitReport @@ -340,9 +341,7 @@ func (mogu *MoguDing) SubmitReport(reportType string, limit int) { } input := fmt.Sprintf("报告类型: %s 工作地点: %s 公司名: %s 岗位职责: %s", _t, mogu.JobInfo.Address, mogu.JobInfo.CompanyName, mogu.JobInfo.JobName) ai := GenerateReportAI(input, limit) - addHeader("userid", mogu.UserId) - addHeader("rolekey", mogu.RoleKey) - addHeader("authorization", mogu.Authorization) + addStandardHeaders(mogu.RoleKey, mogu.UserId, mogu.Authorization) filling := SubmitStructureFilling(mogu, ai, "报告", reportType) sign := utils.CreateSign(mogu.UserId, reportType, mogu.PlanID, "报告") addHeader("sign", sign) diff --git a/main.go b/main.go index 55ae3cd..d222ee9 100644 --- a/main.go +++ b/main.go @@ -14,5 +14,4 @@ func main() { appService := service.NewAppService() appService.Init() - select {} }