2022-03-09 12:30:56 +00:00
|
|
|
package _189
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/http/cookiejar"
|
|
|
|
"net/url"
|
|
|
|
"regexp"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/Xhofe/alist/conf"
|
|
|
|
"github.com/Xhofe/alist/drivers/base"
|
|
|
|
"github.com/Xhofe/alist/model"
|
2022-03-09 14:48:15 +00:00
|
|
|
"github.com/Xhofe/alist/utils"
|
2022-03-09 12:30:56 +00:00
|
|
|
"github.com/go-resty/resty/v2"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
var userStateCache = struct {
|
|
|
|
sync.Mutex
|
|
|
|
States map[string]*State
|
|
|
|
}{States: make(map[string]*State)}
|
|
|
|
|
|
|
|
func GetState(account *model.Account) *State {
|
|
|
|
userStateCache.Lock()
|
|
|
|
defer userStateCache.Unlock()
|
|
|
|
if v, ok := userStateCache.States[account.Username]; ok && v != nil {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
state := &State{client: resty.New().
|
|
|
|
SetHeaders(map[string]string{
|
|
|
|
"Accept": "application/json;charset=UTF-8",
|
2022-03-09 14:48:15 +00:00
|
|
|
"User-Agent": base.UserAgent,
|
2022-04-03 09:56:21 +00:00
|
|
|
}).SetTimeout(base.DefaultTimeout),
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
|
|
|
userStateCache.States[account.Username] = state
|
|
|
|
return state
|
|
|
|
}
|
|
|
|
|
|
|
|
type State struct {
|
|
|
|
sync.Mutex
|
|
|
|
client *resty.Client
|
|
|
|
|
|
|
|
RsaPublicKey string
|
|
|
|
|
|
|
|
SessionKey string
|
|
|
|
SessionSecret string
|
|
|
|
FamilySessionKey string
|
|
|
|
FamilySessionSecret string
|
|
|
|
|
|
|
|
AccessToken string
|
|
|
|
|
|
|
|
//怎么刷新的???
|
|
|
|
RefreshToken string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *State) login(account *model.Account) error {
|
|
|
|
// 清除cookie
|
|
|
|
jar, _ := cookiejar.New(nil)
|
|
|
|
s.client.SetCookieJar(jar)
|
|
|
|
|
|
|
|
var err error
|
|
|
|
var res *resty.Response
|
|
|
|
defer func() {
|
|
|
|
account.Status = "work"
|
|
|
|
if err != nil {
|
|
|
|
account.Status = err.Error()
|
|
|
|
}
|
|
|
|
model.SaveAccount(account)
|
|
|
|
if res != nil {
|
|
|
|
log.Debug(res.String())
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
var param *LoginParam
|
|
|
|
param, err = s.getLoginParam()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// 提交登录
|
|
|
|
s.RsaPublicKey = fmt.Sprintf("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----", param.jRsaKey)
|
|
|
|
res, err = s.client.R().
|
|
|
|
SetHeaders(map[string]string{
|
|
|
|
"Referer": AUTH_URL,
|
|
|
|
"REQID": param.ReqId,
|
|
|
|
"lt": param.Lt,
|
|
|
|
}).
|
|
|
|
SetFormData(map[string]string{
|
|
|
|
"appKey": APP_ID,
|
|
|
|
"accountType": "02",
|
|
|
|
"userName": "{RSA}" + rsaEncrypt(s.RsaPublicKey, account.Username),
|
|
|
|
"password": "{RSA}" + rsaEncrypt(s.RsaPublicKey, account.Password),
|
|
|
|
"validateCode": param.vCodeRS,
|
|
|
|
"captchaToken": param.CaptchaToken,
|
|
|
|
"returnUrl": RETURN_URL,
|
|
|
|
"mailSuffix": "@189.cn",
|
|
|
|
"dynamicCheck": "FALSE",
|
|
|
|
"clientType": CLIENT_TYPE,
|
|
|
|
"cb_SaveName": "1",
|
|
|
|
"isOauth2": "false",
|
|
|
|
"state": "",
|
|
|
|
"paramId": param.ParamId,
|
|
|
|
}).
|
|
|
|
Post(AUTH_URL + "/api/logbox/oauth2/loginSubmit.do")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-03-16 06:22:42 +00:00
|
|
|
toUrl := utils.Json.Get(res.Body(), "toUrl").ToString()
|
2022-03-09 12:30:56 +00:00
|
|
|
if toUrl == "" {
|
|
|
|
log.Error(res.String())
|
|
|
|
return fmt.Errorf(res.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取Session
|
|
|
|
var erron Erron
|
|
|
|
var sessionResp appSessionResp
|
|
|
|
res, err = s.client.R().
|
|
|
|
SetResult(&sessionResp).SetError(&erron).
|
|
|
|
SetQueryParams(clientSuffix()).
|
|
|
|
SetQueryParam("redirectURL", url.QueryEscape(toUrl)).
|
|
|
|
Post(API_URL + "/getSessionForPC.action")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if erron.ResCode != "" {
|
|
|
|
err = fmt.Errorf(erron.ResMessage)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if sessionResp.ResCode != 0 {
|
|
|
|
err = fmt.Errorf(sessionResp.ResMessage)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
s.SessionKey = sessionResp.SessionKey
|
|
|
|
s.SessionSecret = sessionResp.SessionSecret
|
|
|
|
s.FamilySessionKey = sessionResp.FamilySessionKey
|
|
|
|
s.FamilySessionSecret = sessionResp.FamilySessionSecret
|
|
|
|
s.AccessToken = sessionResp.AccessToken
|
|
|
|
s.RefreshToken = sessionResp.RefreshToken
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *State) getLoginParam() (*LoginParam, error) {
|
|
|
|
res, err := s.client.R().
|
|
|
|
SetQueryParams(map[string]string{
|
|
|
|
"appId": APP_ID,
|
|
|
|
"clientType": CLIENT_TYPE,
|
|
|
|
"returnURL": RETURN_URL,
|
|
|
|
"timeStamp": fmt.Sprint(timestamp()),
|
|
|
|
}).
|
|
|
|
Get(WEB_URL + "/api/portal/unifyLoginForPC.action")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-03-09 13:09:21 +00:00
|
|
|
log.Debug(res.String())
|
2022-03-09 12:30:56 +00:00
|
|
|
param := &LoginParam{
|
|
|
|
CaptchaToken: regexp.MustCompile(`'captchaToken' value='(.+?)'`).FindStringSubmatch(res.String())[1],
|
|
|
|
Lt: regexp.MustCompile(`lt = "(.+?)"`).FindStringSubmatch(res.String())[1],
|
|
|
|
ParamId: regexp.MustCompile(`paramId = "(.+?)"`).FindStringSubmatch(res.String())[1],
|
|
|
|
ReqId: regexp.MustCompile(`reqId = "(.+?)"`).FindStringSubmatch(res.String())[1],
|
|
|
|
jRsaKey: regexp.MustCompile(`"j_rsaKey" value="(.+?)"`).FindStringSubmatch(res.String())[1],
|
|
|
|
|
|
|
|
vCodeID: regexp.MustCompile(`token=([A-Za-z0-9&=]+)`).FindStringSubmatch(res.String())[1],
|
|
|
|
}
|
|
|
|
|
|
|
|
imgRes, err := s.client.R().Get(fmt.Sprint(AUTH_URL, "/api/logbox/oauth2/picCaptcha.do?token=", param.vCodeID, timestamp()))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if len(imgRes.Body()) > 0 {
|
|
|
|
vRes, err := resty.New().R().
|
|
|
|
SetMultipartField("image", "validateCode.png", "image/png", bytes.NewReader(imgRes.Body())).
|
|
|
|
Post(conf.GetStr("ocr api"))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-03-16 06:22:42 +00:00
|
|
|
if utils.Json.Get(vRes.Body(), "status").ToInt() != 200 {
|
|
|
|
return nil, errors.New("ocr error:" + utils.Json.Get(vRes.Body(), "msg").ToString())
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
2022-03-16 06:22:42 +00:00
|
|
|
param.vCodeRS = utils.Json.Get(vRes.Body(), "result").ToString()
|
2022-03-09 12:30:56 +00:00
|
|
|
log.Debugln("code: ", param.vCodeRS)
|
|
|
|
}
|
|
|
|
return param, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *State) refreshSession(account *model.Account) error {
|
|
|
|
var erron Erron
|
|
|
|
var userSessionResp UserSessionResp
|
|
|
|
res, err := s.client.R().
|
|
|
|
SetResult(&userSessionResp).SetError(&erron).
|
|
|
|
SetQueryParams(clientSuffix()).
|
|
|
|
SetQueryParams(map[string]string{
|
|
|
|
"appId": APP_ID,
|
|
|
|
"accessToken": s.AccessToken,
|
|
|
|
}).
|
|
|
|
SetHeader("X-Request-ID", uuid.NewString()).
|
2022-04-03 09:56:21 +00:00
|
|
|
Get(API_URL + "/getSessionForPC.action")
|
2022-03-09 12:30:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-03-09 14:48:15 +00:00
|
|
|
log.Debug(res.String())
|
2022-03-09 12:30:56 +00:00
|
|
|
if erron.ResCode != "" {
|
|
|
|
return fmt.Errorf(erron.ResMessage)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch userSessionResp.ResCode {
|
|
|
|
case 0:
|
|
|
|
s.SessionKey = userSessionResp.SessionKey
|
|
|
|
s.SessionSecret = userSessionResp.SessionSecret
|
|
|
|
s.FamilySessionKey = userSessionResp.FamilySessionKey
|
|
|
|
s.FamilySessionSecret = userSessionResp.FamilySessionSecret
|
|
|
|
case 11, 18:
|
|
|
|
return s.login(account)
|
|
|
|
default:
|
|
|
|
account.Status = userSessionResp.ResMessage
|
2022-03-09 13:09:21 +00:00
|
|
|
_ = model.SaveAccount(account)
|
2022-03-09 12:30:56 +00:00
|
|
|
return fmt.Errorf(userSessionResp.ResMessage)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
func (s *State) IsLogin(account *model.Account) bool {
|
|
|
|
_, err := s.Request(http.MethodGet, API_URL+"/getUserInfo.action", nil, func(r *resty.Request) { r.SetQueryParams(clientSuffix()) }, account)
|
2022-03-09 12:30:56 +00:00
|
|
|
return err == nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *State) Login(account *model.Account) error {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
return s.login(account)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *State) RefreshSession(account *model.Account) error {
|
|
|
|
s.Lock()
|
|
|
|
defer s.Unlock()
|
|
|
|
return s.refreshSession(account)
|
|
|
|
}
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
func (s *State) Request(method string, fullUrl string, params Params, callback func(*resty.Request), account *model.Account) (*resty.Response, error) {
|
2022-03-09 12:30:56 +00:00
|
|
|
s.Lock()
|
|
|
|
dateOfGmt := getHttpDateStr()
|
|
|
|
sessionKey := s.SessionKey
|
|
|
|
sessionSecret := s.SessionSecret
|
2022-04-03 09:56:21 +00:00
|
|
|
if isFamily(account) {
|
2022-03-09 12:30:56 +00:00
|
|
|
sessionKey = s.FamilySessionKey
|
|
|
|
sessionSecret = s.FamilySessionSecret
|
|
|
|
}
|
|
|
|
|
|
|
|
req := s.client.R()
|
|
|
|
req.SetHeaders(map[string]string{
|
|
|
|
"Date": dateOfGmt,
|
|
|
|
"SessionKey": sessionKey,
|
|
|
|
"X-Request-ID": uuid.NewString(),
|
|
|
|
})
|
|
|
|
|
|
|
|
// 设置params
|
|
|
|
var paramsData string
|
|
|
|
if params != nil {
|
|
|
|
paramsData = AesECBEncrypt(params.Encode(), s.SessionSecret[:16])
|
|
|
|
req.SetQueryParam("params", paramsData)
|
|
|
|
}
|
|
|
|
req.SetHeader("Signature", signatureOfHmac(sessionSecret, sessionKey, method, fullUrl, dateOfGmt, paramsData))
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
if callback != nil {
|
|
|
|
callback(req)
|
|
|
|
}
|
2022-03-09 12:30:56 +00:00
|
|
|
s.Unlock()
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
res, err := req.Execute(method, fullUrl)
|
2022-03-09 12:30:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
log.Debug(res.String())
|
|
|
|
|
|
|
|
var erron Erron
|
2022-03-09 13:09:21 +00:00
|
|
|
utils.Json.Unmarshal(res.Body(), &erron)
|
2022-03-09 12:30:56 +00:00
|
|
|
if erron.ResCode != "" {
|
|
|
|
return nil, fmt.Errorf(erron.ResMessage)
|
|
|
|
}
|
|
|
|
if erron.Code != "" && erron.Code != "SUCCESS" {
|
|
|
|
if erron.Msg == "" {
|
2022-04-03 09:56:21 +00:00
|
|
|
if erron.Message == "" {
|
|
|
|
return nil, fmt.Errorf(res.String())
|
|
|
|
}
|
2022-03-09 12:30:56 +00:00
|
|
|
return nil, fmt.Errorf(erron.Message)
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf(erron.Msg)
|
|
|
|
}
|
|
|
|
if erron.ErrorCode != "" {
|
|
|
|
return nil, fmt.Errorf(erron.ErrorMsg)
|
|
|
|
}
|
|
|
|
|
2022-04-03 09:56:21 +00:00
|
|
|
switch utils.Json.Get(res.Body(), "res_code").ToInt64() {
|
|
|
|
case 11, 18:
|
|
|
|
if err := s.RefreshSession(account); err != nil {
|
|
|
|
return nil, err
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
2022-04-03 09:56:21 +00:00
|
|
|
return s.Request(method, fullUrl, params, callback, account)
|
|
|
|
case 0:
|
|
|
|
if res.StatusCode() == http.StatusOK {
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf(res.String())
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf(utils.Json.Get(res.Body(), "res_message").ToString())
|
2022-03-09 12:30:56 +00:00
|
|
|
}
|
|
|
|
}
|