// Package model // @Description: package model import ( "net/http" "os" "time" "github.com/playwright-community/playwright-go" "github.com/robfig/cron/v3" log "github.com/sirupsen/logrus" "github.com/sjkhsl/study_xxqg/utils" ) func init() { go check() } var ( pushFunc func(id, kind, message string) ) func SetPush(push func(id, kind, message string)) { pushFunc = push } // Query /** * @Description: 查询所有未掉线的用户 * @return []*User * @return error */ func Query() ([]*User, error) { var ( users []*User result []*User ) _ = engine.Ping() err := engine.Where("status=?", 1).Find(&users) if err != nil { return users, err } for _, user := range users { if ok, _ := utils.CheckUserCookie(user.ToCookies()); ok { result = append(result, user) } else { log.Warningln(user.Nick + "的cookie已失效") changeStatus(user.Uid, 0) if pushFunc != nil { pushFunc(user.PushId, "flush", user.Nick+"的cookie已失效") } } } return result, err } func changeStatus(uid string, status int) { _ = engine.Ping() _, err := engine.Table(new(User)).Where("uid=?", uid).Update(map[string]any{"status": status}) if err != nil { log.Errorln("改变status失败" + err.Error()) return } } func QueryFailUser() ([]*User, error) { var users []*User _ = engine.Ping() err := engine.Where("status=?", 0).Find(&users) if err != nil { return users, err } return users, err } // QueryByPushID /** * @Description: 根据推送平台的key查询用户 * @return []*User * @return error */ func QueryByPushID(pushID string) ([]*User, error) { var ( users []*User result []*User ) _ = engine.Ping() err := engine.Where("status=? and push_id=?", 1, pushID).Find(&users) if err != nil { return users, err } for _, user := range users { if ok, _ := utils.CheckUserCookie(user.ToCookies()); ok { result = append(result, user) } else { log.Warningln(user.Nick + "的cookie已失效") changeStatus(user.Uid, 0) if pushFunc != nil { pushFunc(user.PushId, "flush", user.Nick+"的cookie已失效") } } } return result, err } // Find /** * @Description: * @param uid * @return *User */ func Find(uid string) *User { u := new(User) _, err := engine.Where("uid=?", uid).Get(u) if err != nil { return nil } return u } // AddUser /** * @Description: * @param user * @return error */ func AddUser(user *User) error { _ = engine.Ping() count, _ := engine.Where("uid=?", user.Uid).Count(new(User)) if count < 1 { user.Status = 1 _, err := engine.InsertOne(user) if err != nil { return err } } else { user.Status = 1 err := UpdateUser(user) if err != nil { return err } } return nil } // UpdateUser /** * @Description: * @param user * @return error */ func UpdateUser(user *User) error { _, err := engine.Where("uid=?", user.Uid).Update(user) if err != nil { return err } return nil } // DeleteUser /* @Description: * @param uid * @return error */ func DeleteUser(uid string) error { _ = engine.Ping() _, err := engine.Where("uid=?", uid).Delete(new(User)) if err != nil { return err } return err } // ToCookies /** * @Description: 获取user的cookie * @receiver u * @return []*http.Cookie */ func (u *User) ToCookies() []*http.Cookie { cookie := &http.Cookie{ Name: "token", Value: u.Token, Path: "/", Domain: "xuexi.cn", Expires: time.Now().Add(time.Hour * 12), Secure: false, HttpOnly: false, SameSite: http.SameSiteStrictMode, } return []*http.Cookie{cookie} } func TokenToCookies(token string) []*http.Cookie { cookie := &http.Cookie{ Name: "token", Value: token, Path: "/", Domain: "xuexi.cn", Expires: time.Now().Add(time.Hour * 12), Secure: false, HttpOnly: false, SameSite: http.SameSiteStrictMode, } return []*http.Cookie{cookie} } func (u *User) ToBrowserCookies() []playwright.BrowserContextAddCookiesOptionsCookies { cookie := playwright.BrowserContextAddCookiesOptionsCookies{ Name: playwright.String("token"), Value: playwright.String(u.Token), Path: playwright.String("/"), Domain: playwright.String(".xuexi.cn"), Expires: playwright.Float(float64(time.Now().Add(time.Hour * 12).Unix())), Secure: playwright.Bool(false), HttpOnly: playwright.Bool(false), SameSite: playwright.SameSiteAttributeStrict, } return []playwright.BrowserContextAddCookiesOptionsCookies{cookie} } func check() { defer func() { err := recover() if err != nil { log.Errorf("%v 出现错误,%v", "auth check", err) } }() c := cron.New() cr := "0 */1 * * *" if crEnv, ok := os.LookupEnv("CHECK_ENV"); ok { cr = crEnv log.Infoln("已成功自定义保活cron : " + cr) } _, err := c.AddFunc(cr, func() { log.Infoln("开始执行保活任务") users, _ := Query() for _, user := range users { response, _ := utils.GetClient().R().SetCookies(user.ToCookies()...).Get("https://pc-api.xuexi.cn/open/api/auth/check") token := "" for _, cookie := range response.Cookies() { if cookie.Name == "token" { token = cookie.Value } } if token != "" && user.Token != token { user.Token = token _ = UpdateUser(user) log.Infoln("用户" + user.Nick + "的ck已成功保活cookie") } } }) if err != nil { log.Errorln("添加保活任务失败" + err.Error()) return } c.Start() }