302 lines
6.2 KiB
Go
302 lines
6.2 KiB
Go
// Package model
|
||
// @Description:
|
||
package model
|
||
|
||
import (
|
||
"database/sql"
|
||
"fmt"
|
||
"math/rand"
|
||
"net/http"
|
||
"time"
|
||
|
||
"github.com/guonaihong/gout"
|
||
"github.com/imroc/req/v3"
|
||
"github.com/playwright-community/playwright-go"
|
||
log "github.com/sirupsen/logrus"
|
||
"github.com/tidwall/gjson"
|
||
|
||
"github.com/johlanse/study_xxqg/conf"
|
||
)
|
||
|
||
func init() {
|
||
go check()
|
||
}
|
||
|
||
var (
|
||
wechatPush func(id, message string)
|
||
)
|
||
|
||
func SetPush(push func(id, message string)) {
|
||
wechatPush = push
|
||
}
|
||
|
||
// User
|
||
/**
|
||
* @Description:
|
||
*/
|
||
type User struct {
|
||
Nick string `json:"nick"`
|
||
UID string `json:"uid"`
|
||
Token string `json:"token"`
|
||
LoginTime int64 `json:"login_time"`
|
||
PushId string `json:"push_id"`
|
||
}
|
||
|
||
// Query
|
||
/**
|
||
* @Description:
|
||
* @return []*User
|
||
* @return error
|
||
*/
|
||
func Query() ([]*User, error) {
|
||
var users []*User
|
||
ping()
|
||
results, err := db.Query("select * from user")
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
defer func(results *sql.Rows) {
|
||
err := results.Close()
|
||
if err != nil {
|
||
log.Errorln("关闭results失败" + err.Error())
|
||
}
|
||
}(results)
|
||
for results.Next() {
|
||
u := new(User)
|
||
err := results.Scan(&u.Nick, &u.UID, &u.Token, &u.LoginTime, &u.PushId)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if CheckUserCookie(u) {
|
||
users = append(users, u)
|
||
} else {
|
||
log.Infoln("用户" + u.Nick + "cookie已失效")
|
||
//_ = push.PushMessage("", "用户"+u.UID+"已失效,请登录", "login", u.PushId)
|
||
if conf.GetConfig().Wechat.PushLoginWarn {
|
||
wechatPush(u.PushId, fmt.Sprintf("用户%v已失效!!", u.Nick))
|
||
}
|
||
_ = DeleteUser(u.UID)
|
||
}
|
||
}
|
||
return users, err
|
||
}
|
||
|
||
// QueryByPushID
|
||
/**
|
||
* @Description:
|
||
* @return []*User
|
||
* @return error
|
||
*/
|
||
func QueryByPushID(pushID string) ([]*User, error) {
|
||
var users []*User
|
||
ping()
|
||
results, err := db.Query("select * from user where push_id = ?", pushID)
|
||
if err != nil {
|
||
return users, err
|
||
}
|
||
defer func(results *sql.Rows) {
|
||
err := results.Close()
|
||
if err != nil {
|
||
log.Errorln("关闭results失败" + err.Error())
|
||
}
|
||
}(results)
|
||
for results.Next() {
|
||
u := new(User)
|
||
err := results.Scan(&u.Nick, &u.UID, &u.Token, &u.LoginTime, &u.PushId)
|
||
if err != nil {
|
||
return users, err
|
||
}
|
||
if CheckUserCookie(u) {
|
||
users = append(users, u)
|
||
} else {
|
||
log.Infoln("用户" + u.Nick + "cookie已失效")
|
||
//_ = push.PushMessage("", "用户"+u.UID+"已失效,请登录", "login", u.PushId)
|
||
_ = DeleteUser(u.UID)
|
||
}
|
||
}
|
||
return users, err
|
||
}
|
||
|
||
// Find
|
||
/**
|
||
* @Description:
|
||
* @param uid
|
||
* @return *User
|
||
*/
|
||
func Find(uid string) *User {
|
||
u := new(User)
|
||
err := db.QueryRow("select * from user where uid=?;", uid).Scan(&u.Nick, &u.UID, &u.Token, &u.LoginTime, &u.PushId)
|
||
if err != nil {
|
||
return nil
|
||
}
|
||
return u
|
||
}
|
||
|
||
// AddUser
|
||
/**
|
||
* @Description:
|
||
* @param user
|
||
* @return error
|
||
*/
|
||
func AddUser(user *User) error {
|
||
ping()
|
||
count := UserCount(user.UID)
|
||
if count < 1 {
|
||
_, err := db.Exec("insert into user (nick, uid, token, login_time,push_id) values (?,?,?,?,?)", user.Nick, user.UID, user.Token, user.LoginTime, user.PushId)
|
||
if err != nil {
|
||
log.Errorln("数据库插入失败")
|
||
log.Errorln(err.Error())
|
||
return err
|
||
}
|
||
return err
|
||
}
|
||
err := UpdateUser(user)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// UpdateUser
|
||
/**
|
||
* @Description:
|
||
* @param user
|
||
* @return error
|
||
*/
|
||
func UpdateUser(user *User) error {
|
||
ping()
|
||
_, err := db.Exec("update user set token=?,login_time=?,push_id=? where uid = ?", user.Token, user.LoginTime, user.PushId, user.UID)
|
||
if err != nil {
|
||
log.Errorln("更新数据失败")
|
||
log.Errorln(err.Error())
|
||
return err
|
||
}
|
||
return err
|
||
}
|
||
|
||
// UserCount
|
||
/**
|
||
* @Description:
|
||
* @param uid
|
||
* @return int
|
||
*/
|
||
func UserCount(uid string) int {
|
||
ping()
|
||
var count int
|
||
err := db.QueryRow("select count(*) from user where uid = ?", uid).Scan(&count)
|
||
if err != nil {
|
||
return 0
|
||
}
|
||
return count
|
||
}
|
||
|
||
// DeleteUser
|
||
/* @Description:
|
||
* @param uid
|
||
* @return error
|
||
*/
|
||
func DeleteUser(uid string) error {
|
||
ping()
|
||
_, err := db.Exec("delete from user where uid = ?;", uid)
|
||
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}
|
||
}
|
||
|
||
// CheckUserCookie
|
||
/**
|
||
* @Description: 获取用户成绩
|
||
* @param user
|
||
* @return bool
|
||
*/
|
||
func CheckUserCookie(user *User) bool {
|
||
var resp []byte
|
||
err := gout.GET("https://pc-api.xuexi.cn/open/api/score/get").SetCookies(user.ToCookies()...).SetHeader(gout.H{
|
||
"Cache-Control": "no-cache",
|
||
}).BindBody(&resp).Do()
|
||
if err != nil {
|
||
log.Errorln("获取用户总分错误" + err.Error())
|
||
|
||
return false
|
||
}
|
||
if !gjson.GetBytes(resp, "ok").Bool() {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
func check() {
|
||
defer func() {
|
||
err := recover()
|
||
if err != nil {
|
||
log.Errorf("%v 出现错误,%v", "auth check", err)
|
||
}
|
||
}()
|
||
for {
|
||
users, _ := Query()
|
||
for _, user := range users {
|
||
response, _ := req.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
|
||
_ = UpdateUser(user)
|
||
}
|
||
}
|
||
time.Sleep(time.Hour * time.Duration(rand.Intn(2)))
|
||
}
|
||
}
|