Skip to content

Commit

Permalink
feat(thunderx): add automatically generate UserAgent
Browse files Browse the repository at this point in the history
  • Loading branch information
Three-taile-dragon committed Jun 28, 2024
1 parent 29fe49f commit 8f0bf07
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 48 deletions.
110 changes: 70 additions & 40 deletions drivers/thunderx/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ package thunderx
import (
"context"
"fmt"
"github.com/go-resty/resty/v2"
"net/http"
"strings"

"github.com/alist-org/alist/v3/drivers/base"
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/errs"
Expand All @@ -18,6 +14,9 @@ import (
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/go-resty/resty/v2"
"net/http"
"strings"
)

type ThunderX struct {
Expand All @@ -41,26 +40,15 @@ func (x *ThunderX) Init(ctx context.Context) (err error) {
if x.XunLeiXCommon == nil {
x.XunLeiXCommon = &XunLeiXCommon{
Common: &Common{
client: base.NewRestyClient(),
Algorithms: []string{
"lHwINjLeqssT28Ym99p5MvR",
"xvFcxvtqPKCa9Ajf",
"2ywOP8spKHzfuhZMUYZ9IpsViq0t8vT0",
"FTBrJism20SHKQ2m2",
"BHrWJsPwjnr5VeLtOUr2191X9uXhWmt",
"yu0QgHEjNmDoPNwXN17so2hQlDT83T",
"OcaMfLMCGZ7oYlvZGIbTqb4U7cCY",
"jBGGu0GzXOjtCXYwkOBb+c6TZ/Nymv",
"YLWRjVor2rOuYEL",
"94wjoPazejyNC+gRpOj+JOm1XXvxa",
},
client: base.NewRestyClient(),
Algorithms: Algorithms,
DeviceID: utils.GetMD5EncodeStr(x.Username + x.Password),
ClientID: "ZQL_zwA4qhHcoe_2",
ClientSecret: "Og9Vr1L8Ee6bh0olFxFDRg",
ClientVersion: "1.05.0.2115",
PackageName: "com.thunder.downloader",
UserAgent: "ANDROID-com.thunder.downloader/1.05.0.2115 netWorkType/5G appid/40 deviceName/Xiaomi_M2004j7ac deviceModel/M2004J7AC OSVersion/12 protocolVersion/301 platformVersion/10 sdkVersion/220200 Oauth2Client/0.9 (Linux 4_14_186-perf-gddfs8vbb238b) (JAVA 0)",
DownloadUserAgent: "Dalvik/2.1.0 (Linux; U; Android 12; M2004J7AC Build/SP1A.210812.016)",
ClientID: ClientID,
ClientSecret: ClientSecret,
ClientVersion: ClientVersion,
PackageName: PackageName,
UserAgent: BuildCustomUserAgent(utils.GetMD5EncodeStr(x.Username+x.Password), ClientID, PackageName, SdkVersion, ClientVersion, PackageName, ""),
DownloadUserAgent: DownloadUserAgent,
UseVideoUrl: x.UseVideoUrl,

refreshCTokenCk: func(token string) {
Expand All @@ -76,6 +64,10 @@ func (x *ThunderX) Init(ctx context.Context) (err error) {
token, err = x.Login(x.Username, x.Password)
if err != nil {
x.GetStorage().SetStatus(fmt.Sprintf("%+v", err.Error()))
if token.UserID != "" {
x.SetUserID(token.UserID)
x.UserAgent = BuildCustomUserAgent(utils.GetMD5EncodeStr(x.Username+x.Password), ClientID, PackageName, SdkVersion, ClientVersion, PackageName, token.UserID)
}
op.MustSaveDriverStorage(x)
}
}
Expand All @@ -86,10 +78,14 @@ func (x *ThunderX) Init(ctx context.Context) (err error) {
}

// 自定义验证码token
ctoekn := strings.TrimSpace(x.CaptchaToken)
if ctoekn != "" {
x.SetCaptchaToken(ctoekn)
ctoken := strings.TrimSpace(x.CaptchaToken)
if ctoken != "" {
x.SetCaptchaToken(ctoken)
}
if x.DeviceID == "" {
x.SetDeviceID(utils.GetMD5EncodeStr(x.Username + x.Password))
}

x.XunLeiXCommon.UseVideoUrl = x.UseVideoUrl
x.Addition.RootFolderID = x.RootFolderID
// 防止重复登录
Expand All @@ -102,6 +98,10 @@ func (x *ThunderX) Init(ctx context.Context) (err error) {
return err
}
x.SetTokenResp(token)
if token.UserID != "" {
x.SetUserID(token.UserID)
x.UserAgent = BuildCustomUserAgent(x.DeviceID, ClientID, PackageName, SdkVersion, ClientVersion, PackageName, token.UserID)
}
}
return nil
}
Expand Down Expand Up @@ -137,27 +137,51 @@ func (x *ThunderXExpert) Init(ctx context.Context) (err error) {

DeviceID: func() string {
if len(x.DeviceID) != 32 {
return utils.GetMD5EncodeStr(x.DeviceID)
if x.LoginType == "user" {
return utils.GetMD5EncodeStr(x.Username + x.Password)
}
return utils.GetMD5EncodeStr(x.ExpertAddition.RefreshToken)
}
return x.DeviceID
}(),
ClientID: x.ClientID,
ClientSecret: x.ClientSecret,
ClientVersion: x.ClientVersion,
PackageName: x.PackageName,
UserAgent: x.UserAgent,
DownloadUserAgent: x.DownloadUserAgent,
UseVideoUrl: x.UseVideoUrl,

ClientID: x.ClientID,
ClientSecret: x.ClientSecret,
ClientVersion: x.ClientVersion,
PackageName: x.PackageName,
UserAgent: func() string {
if x.ExpertAddition.UserAgent != "" {
return x.ExpertAddition.UserAgent
}
if x.LoginType == "user" {
return BuildCustomUserAgent(utils.GetMD5EncodeStr(x.Username+x.Password), ClientID, PackageName, SdkVersion, ClientVersion, PackageName, "")
}
return BuildCustomUserAgent(utils.GetMD5EncodeStr(x.ExpertAddition.RefreshToken), ClientID, PackageName, SdkVersion, ClientVersion, PackageName, "")
}(),
DownloadUserAgent: func() string {
if x.ExpertAddition.DownloadUserAgent != "" {
return x.ExpertAddition.DownloadUserAgent
}
return DownloadUserAgent
}(),
UseVideoUrl: x.UseVideoUrl,
refreshCTokenCk: func(token string) {
x.CaptchaToken = token
op.MustSaveDriverStorage(x)
},
},
}

if x.CaptchaToken != "" {
x.SetCaptchaToken(x.CaptchaToken)
if x.ExpertAddition.CaptchaToken != "" {
x.SetCaptchaToken(x.ExpertAddition.CaptchaToken)
op.MustSaveDriverStorage(x)
}
if x.Common.DeviceID != "" {
x.ExpertAddition.DeviceID = x.Common.DeviceID
op.MustSaveDriverStorage(x)
}
if x.Common.DownloadUserAgent != "" {
x.ExpertAddition.DownloadUserAgent = x.Common.DownloadUserAgent
op.MustSaveDriverStorage(x)
}
x.XunLeiXCommon.UseVideoUrl = x.UseVideoUrl
x.ExpertAddition.RootFolderID = x.RootFolderID
Expand All @@ -177,7 +201,6 @@ func (x *ThunderXExpert) Init(ctx context.Context) (err error) {
return err
}
x.SetTokenResp(token)

// 刷新token方法
x.SetRefreshTokenFunc(func() error {
token, err := x.XunLeiXCommon.RefreshToken(x.TokenResp.RefreshToken)
Expand Down Expand Up @@ -208,13 +231,19 @@ func (x *ThunderXExpert) Init(ctx context.Context) (err error) {
return err
})
}
// 更新 UserAgent
if x.TokenResp.UserID != "" {
x.ExpertAddition.UserAgent = BuildCustomUserAgent(x.ExpertAddition.DeviceID, ClientID, PackageName, SdkVersion, ClientVersion, PackageName, x.TokenResp.UserID)
x.SetUserAgent(x.ExpertAddition.UserAgent)
op.MustSaveDriverStorage(x)
}
} else {
// 仅修改验证码token
if x.CaptchaToken != "" {
x.SetCaptchaToken(x.CaptchaToken)
}
x.XunLeiXCommon.UserAgent = x.UserAgent
x.XunLeiXCommon.DownloadUserAgent = x.DownloadUserAgent
x.XunLeiXCommon.UserAgent = x.ExpertAddition.UserAgent
x.XunLeiXCommon.DownloadUserAgent = x.ExpertAddition.UserAgent
x.XunLeiXCommon.UseVideoUrl = x.UseVideoUrl
x.ExpertAddition.RootFolderID = x.RootFolderID
}
Expand Down Expand Up @@ -491,6 +520,7 @@ func (xc *XunLeiXCommon) RefreshToken(refreshToken string) (*TokenResp, error) {
if resp.RefreshToken == "" {
return nil, errs.EmptyToken
}
resp.UserID = resp.Sub
return &resp, nil
}

Expand Down
14 changes: 7 additions & 7 deletions drivers/thunderx/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type ExpertAddition struct {
RefreshToken string `json:"refresh_token" required:"true" help:"login type is refresh_token,this is required"`

// 签名方法1
Algorithms string `json:"algorithms" required:"true" help:"sign type is algorithms,this is required" default:"lHwINjLeqssT28Ym99p5MvR,xvFcxvtqPKCa9Ajf,2ywOP8spKHzfuhZMUYZ9IpsViq0t8vT0,FTBrJism20SHKQ2m2,BHrWJsPwjnr5VeLtOUr2191X9uXhWmt,yu0QgHEjNmDoPNwXN17so2hQlDT83T,OcaMfLMCGZ7oYlvZGIbTqb4U7cCY,jBGGu0GzXOjtCXYwkOBb+c6TZ/Nymv,YLWRjVor2rOuYEL,94wjoPazejyNC+gRpOj+JOm1XXvxa"`
Algorithms string `json:"algorithms" required:"true" help:"sign type is algorithms,this is required" default:"IzcnB/ji8O8SE/JiilzZl9qDn9B,eSTVfCx,pHhe8E7Agix4ghXOE,+u,lHOCwF3Vy84o8uI5XEGFqq/roefG,MCGSwKZQEGp/ldfe8F,WA+qjJQoJowdW9MQ4j5N,X5wtKA/0YmTJxnh5,fWOAGeXZs/sC7XDF8aRyKjkEJ,FU5i8SPMcNmEppcfcXJYBd9owjXM,2YBwM,epWc3vvH0iaeMrXNeSmzlzgP,VD3rU,XAJ,2BPoWVPReg1VVjJNqOSr7psH"`
// 签名方法2
CaptchaSign string `json:"captcha_sign" required:"true" help:"sign type is captcha_sign,this is required"`
Timestamp string `json:"timestamp" required:"true" help:"sign type is captcha_sign,this is required"`
Expand All @@ -32,15 +32,15 @@ type ExpertAddition struct {
CaptchaToken string `json:"captcha_token"`

// 必要且影响登录,由签名决定
DeviceID string `json:"device_id" required:"true" default:"9aa5c268e7bcfc197a9ad88e2fb330e5"`
DeviceID string `json:"device_id" required:"false" default:""`
ClientID string `json:"client_id" required:"true" default:"ZQL_zwA4qhHcoe_2"`
ClientSecret string `json:"client_secret" required:"true" default:"Og9Vr1L8Ee6bh0olFxFDRg"`
ClientVersion string `json:"client_version" required:"true" default:"1.05.0.2115"`
ClientVersion string `json:"client_version" required:"true" default:"1.06.0.2131"`
PackageName string `json:"package_name" required:"true" default:"com.thunder.downloader"`

//不影响登录,影响下载速度
UserAgent string `json:"user_agent" required:"true" default:"ANDROID-com.thunder.downloader/1.05.0.2115 netWorkType/4G appid/40 deviceName/Xiaomi_M2004j7ac deviceModel/M2004J7AC OSVersion/12 protocolVersion/301 platformVersion/10 sdkVersion/220200 Oauth2Client/0.9 (Linux 4_14_186-perf-gdcf98eab238b) (JAVA 0)"`
DownloadUserAgent string `json:"download_user_agent" required:"true" default:"Dalvik/2.1.0 (Linux; U; Android 12; M2004J7AC Build/SP1A.210812.016)"`
////不影响登录,影响下载速度
UserAgent string `json:"user_agent" required:"false" default:""`
DownloadUserAgent string `json:"download_user_agent" required:"false" default:""`

//优先使用视频链接代替下载链接
UseVideoUrl bool `json:"use_video_url"`
Expand Down Expand Up @@ -85,7 +85,7 @@ func (i *Addition) GetIdentity() string {
var config = driver.Config{
Name: "ThunderX",
LocalSort: true,
OnlyProxy: true,
OnlyProxy: false,
}

var configExpert = driver.Config{
Expand Down
97 changes: 96 additions & 1 deletion drivers/thunderx/util.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package thunderx

import (
"crypto/md5"
"crypto/sha1"
"encoding/hex"
"fmt"
"io"
"net/http"
"regexp"
"strings"
"time"

"github.com/alist-org/alist/v3/drivers/base"
Expand All @@ -20,6 +22,33 @@ const (
XLUSER_API_URL = "https://xluser-ssl.xunleix.com/v1"
)

var Algorithms = []string{
"IzcnB/ji8O8SE/JiilzZl9qDn9B",
"eSTVfCx",
"pHhe8E7Agix4ghXOE",
"+u",
"lHOCwF3Vy84o8uI5XEGFqq/roefG",
"MCGSwKZQEGp/ldfe8F",
"WA+qjJQoJowdW9MQ4j5N",
"X5wtKA/0YmTJxnh5",
"fWOAGeXZs/sC7XDF8aRyKjkEJ",
"FU5i8SPMcNmEppcfcXJYBd9owjXM",
"2YBwM",
"epWc3vvH0iaeMrXNeSmzlzgP",
"VD3rU",
"XAJ",
"2BPoWVPReg1VVjJNqOSr7psH",
}

const (
ClientID = "ZQL_zwA4qhHcoe_2"
ClientSecret = "Og9Vr1L8Ee6bh0olFxFDRg"
ClientVersion = "1.06.0.2131"
PackageName = "com.thunder.downloader"
DownloadUserAgent = "Dalvik/2.1.0 (Linux; U; Android 12; M2004J7AC Build/SP1A.210812.016)"
SdkVersion = "2.0.3.203100 "
)

const (
FOLDER = "drive#folder"
FILE = "drive#file"
Expand All @@ -42,7 +71,7 @@ type Common struct {
client *resty.Client

captchaToken string

userID string
// 签名相关,二选一
Algorithms []string
Timestamp, CaptchaSign string
Expand All @@ -61,6 +90,18 @@ type Common struct {
refreshCTokenCk func(token string)
}

func (c *Common) SetDeviceID(deviceID string) {
c.DeviceID = deviceID
}

func (c *Common) SetUserID(userID string) {
c.userID = userID
}

func (c *Common) SetUserAgent(userAgent string) {
c.UserAgent = userAgent
}

func (c *Common) SetCaptchaToken(captchaToken string) {
c.captchaToken = captchaToken
}
Expand Down Expand Up @@ -200,3 +241,57 @@ func getGcid(r io.Reader, size int64) (string, error) {
}
return hex.EncodeToString(hash1.Sum(nil)), nil
}

func generateDeviceSign(deviceID, packageName string) string {

signatureBase := fmt.Sprintf("%s%s%s%s", deviceID, packageName, "1", "appkey")

sha1Hash := sha1.New()
sha1Hash.Write([]byte(signatureBase))
sha1Result := sha1Hash.Sum(nil)

sha1String := hex.EncodeToString(sha1Result)

md5Hash := md5.New()
md5Hash.Write([]byte(sha1String))
md5Result := md5Hash.Sum(nil)

md5String := hex.EncodeToString(md5Result)

deviceSign := fmt.Sprintf("div101.%s%s", deviceID, md5String)

return deviceSign
}

func BuildCustomUserAgent(deviceID, clientID, appName, sdkVersion, clientVersion, packageName, userID string) string {
deviceSign := generateDeviceSign(deviceID, packageName)
var sb strings.Builder

sb.WriteString(fmt.Sprintf("ANDROID-%s/%s ", appName, clientVersion))
sb.WriteString("protocolVersion/200 ")
sb.WriteString("accesstype/ ")
sb.WriteString(fmt.Sprintf("clientid/%s ", clientID))
sb.WriteString(fmt.Sprintf("clientversion/%s ", clientVersion))
sb.WriteString("action_type/ ")
sb.WriteString("networktype/WIFI ")
sb.WriteString("sessionid/ ")
sb.WriteString(fmt.Sprintf("deviceid/%s ", deviceID))
sb.WriteString("providername/NONE ")
sb.WriteString(fmt.Sprintf("devicesign/%s ", deviceSign))
sb.WriteString("refresh_token/ ")
sb.WriteString(fmt.Sprintf("sdkversion/%s ", sdkVersion))
sb.WriteString(fmt.Sprintf("datetime/%d ", time.Now().UnixMilli()))
sb.WriteString(fmt.Sprintf("usrno/%s ", userID))
sb.WriteString(fmt.Sprintf("appname/%s ", appName))
sb.WriteString(fmt.Sprintf("session_origin/ "))
sb.WriteString(fmt.Sprintf("grant_type/ "))
sb.WriteString(fmt.Sprintf("appid/ "))
sb.WriteString(fmt.Sprintf("clientip/ "))
sb.WriteString(fmt.Sprintf("devicename/Xiaomi_M2004j7ac "))
sb.WriteString(fmt.Sprintf("osversion/13 "))
sb.WriteString(fmt.Sprintf("platformversion/10 "))
sb.WriteString(fmt.Sprintf("accessmode/ "))
sb.WriteString(fmt.Sprintf("devicemodel/M2004J7AC "))

return sb.String()
}

0 comments on commit 8f0bf07

Please sign in to comment.