alist/drivers/xunlei/xunlei.go

226 lines
4.5 KiB
Go
Raw Normal View History

2022-03-03 07:44:41 +00:00
package xunlei
import (
"fmt"
2022-03-17 13:13:13 +00:00
"net/http"
2022-03-03 07:44:41 +00:00
"sync"
"time"
"github.com/Xhofe/alist/drivers/base"
"github.com/Xhofe/alist/model"
"github.com/Xhofe/alist/utils"
"github.com/go-resty/resty/v2"
log "github.com/sirupsen/logrus"
)
2022-04-28 15:15:37 +00:00
var xunleiClient = resty.New().
SetHeaders(map[string]string{
"Accept": "application/json;charset=UTF-8",
}).
SetTimeout(base.DefaultTimeout)
2022-03-03 07:44:41 +00:00
2022-04-28 15:15:37 +00:00
var userClients sync.Map
2022-03-03 07:44:41 +00:00
2022-04-28 15:15:37 +00:00
func GetClient(account *model.Account) *Client {
if v, ok := userClients.Load(account.Username); ok {
return v.(*Client)
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
client := &Client{
Client: xunleiClient,
driverID: getDriverID(account.Username),
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
userClients.Store(account.Username, client)
return client
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
type Client struct {
*resty.Client
sync.Mutex
2022-03-03 07:44:41 +00:00
2022-04-28 15:15:37 +00:00
driverID string
captchaToken string
2022-03-03 07:44:41 +00:00
2022-04-28 15:15:37 +00:00
token string
refreshToken string
userID string
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
// 请求验证码token
func (c *Client) requestCaptchaToken(action string, meta map[string]string) error {
req := CaptchaTokenRequest{
2022-03-03 07:44:41 +00:00
Action: action,
2022-04-28 15:15:37 +00:00
CaptchaToken: c.captchaToken,
2022-03-03 07:44:41 +00:00
ClientID: CLIENT_ID,
2022-04-28 15:15:37 +00:00
DeviceID: c.driverID,
Meta: meta,
2022-03-03 07:44:41 +00:00
}
var e Erron
var resp CaptchaTokenResponse
_, err := xunleiClient.R().
2022-04-28 15:15:37 +00:00
SetBody(&req).
2022-03-03 07:44:41 +00:00
SetError(&e).
SetResult(&resp).
2022-03-17 13:13:13 +00:00
Post(XLUSER_API_URL + "/shield/captcha/init")
2022-03-03 07:44:41 +00:00
if err != nil {
2022-04-28 15:15:37 +00:00
return err
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
if e.ErrorCode != 0 || e.ErrorMsg != "" {
return &e
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
2022-03-03 07:44:41 +00:00
if resp.Url != "" {
2022-04-28 15:15:37 +00:00
return fmt.Errorf("need verify:%s", resp.Url)
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
if resp.CaptchaToken == "" {
return fmt.Errorf("empty captchaToken")
}
c.captchaToken = resp.CaptchaToken
return nil
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
// 登录
func (c *Client) Login(account *model.Account) (err error) {
c.Lock()
defer c.Unlock()
2022-03-03 07:44:41 +00:00
2022-04-28 15:15:37 +00:00
defer func() {
if err != nil {
account.Status = err.Error()
} else {
account.Status = "work"
}
model.SaveAccount(account)
}()
2022-03-03 07:44:41 +00:00
2022-03-17 13:13:13 +00:00
url := XLUSER_API_URL + "/auth/signin"
2022-04-28 15:15:37 +00:00
err = c.requestCaptchaToken(getAction(http.MethodPost, url), map[string]string{"username": account.Username})
2022-03-03 07:44:41 +00:00
if err != nil {
return err
}
var e Erron
var resp TokenResponse
_, err = xunleiClient.R().
SetResult(&resp).
SetError(&e).
2022-04-28 15:15:37 +00:00
SetBody(&SignInRequest{
CaptchaToken: c.captchaToken,
ClientID: CLIENT_ID,
ClientSecret: CLIENT_SECRET,
Username: account.Username,
Password: account.Password,
}).
2022-03-03 07:44:41 +00:00
Post(url)
if err != nil {
return err
}
2022-04-28 15:15:37 +00:00
if e.ErrorCode != 0 || e.ErrorMsg != "" {
return &e
}
if resp.RefreshToken == "" {
return base.ErrEmptyToken
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
c.token = resp.Token()
c.refreshToken = resp.RefreshToken
c.userID = resp.UserID
2022-03-03 07:44:41 +00:00
return nil
}
2022-04-28 15:15:37 +00:00
// 刷新验证码token
func (c *Client) RefreshCaptchaToken(action string) error {
c.Lock()
defer c.Unlock()
ctime := time.Now().UnixMilli()
return c.requestCaptchaToken(action, map[string]string{
"captcha_sign": captchaSign(c.driverID, ctime),
"client_version": CLIENT_VERSION,
"package_name": PACKAGE_NAME,
"timestamp": fmt.Sprint(ctime),
"user_id": c.userID,
})
}
// 刷新token
func (c *Client) RefreshToken() error {
c.Lock()
defer c.Unlock()
2022-03-03 07:44:41 +00:00
2022-04-28 15:15:37 +00:00
var e Erron
var resp TokenResponse
_, err := xunleiClient.R().
SetError(&e).
SetResult(&resp).
SetBody(&base.Json{
"grant_type": "refresh_token",
"refresh_token": c.refreshToken,
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
}).
Post(XLUSER_API_URL + "/auth/token")
2022-03-03 07:44:41 +00:00
if err != nil {
2022-04-28 15:15:37 +00:00
return err
}
if e.ErrorCode != 0 || e.ErrorMsg != "" {
return &e
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
c.token = resp.TokenType + " " + resp.AccessToken
c.refreshToken = resp.RefreshToken
c.userID = resp.UserID
return nil
}
2022-03-17 13:13:13 +00:00
2022-04-28 15:15:37 +00:00
func (c *Client) Request(method string, url string, callback func(*resty.Request), account *model.Account) (*resty.Response, error) {
c.Lock()
2022-03-03 07:44:41 +00:00
req := xunleiClient.R().
2022-03-17 13:13:13 +00:00
SetHeaders(map[string]string{
2022-04-28 15:15:37 +00:00
"X-Device-Id": c.driverID,
"Authorization": c.token,
"X-Captcha-Token": c.captchaToken,
2022-03-17 13:13:13 +00:00
}).
2022-03-03 07:44:41 +00:00
SetQueryParam("client_id", CLIENT_ID)
2022-04-28 15:15:37 +00:00
if callback != nil {
callback(req)
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
c.Unlock()
2022-03-03 07:44:41 +00:00
2022-04-28 15:15:37 +00:00
res, err := req.Execute(method, url)
2022-03-03 07:44:41 +00:00
if err != nil {
2022-03-17 13:13:13 +00:00
return nil, err
2022-03-03 07:44:41 +00:00
}
2022-03-17 13:13:13 +00:00
log.Debug(res.String())
2022-03-03 07:44:41 +00:00
2022-03-17 13:13:13 +00:00
var e Erron
2022-04-28 15:15:37 +00:00
if err = utils.Json.Unmarshal(res.Body(), &e); err != nil {
return nil, err
}
2022-04-28 15:15:37 +00:00
// 处理错误
2022-03-03 07:44:41 +00:00
switch e.ErrorCode {
2022-04-28 15:15:37 +00:00
case 0:
return res, nil
case 4122, 4121: // token过期
if err = c.RefreshToken(); err == nil {
break
}
2022-03-03 07:44:41 +00:00
fallthrough
2022-04-28 15:15:37 +00:00
case 16: // 登录失效
if err = c.Login(account); err != nil {
return nil, err
}
case 9: // 验证码token过期
if err = c.RefreshCaptchaToken(getAction(method, url)); err != nil {
return nil, err
2022-03-17 13:13:13 +00:00
}
2022-03-03 07:44:41 +00:00
default:
2022-04-28 15:15:37 +00:00
return nil, &e
2022-03-03 07:44:41 +00:00
}
2022-04-28 15:15:37 +00:00
return c.Request(method, url, callback, account)
2022-03-03 07:44:41 +00:00
}