Skip to content

Commit

Permalink
feat(thunderBrowser): add automatically generate UserAgent (#6692)
Browse files Browse the repository at this point in the history
  • Loading branch information
Three-taile-dragon authored Jul 7, 2024
1 parent 2705877 commit 316f356
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 57 deletions.
118 changes: 71 additions & 47 deletions drivers/thunder_browser/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package thunder_browser

import (
"context"
"errors"
"fmt"
"github.com/alist-org/alist/v3/drivers/base"
"github.com/alist-org/alist/v3/internal/driver"
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/pkg/utils"
Expand Down Expand Up @@ -53,33 +53,17 @@ func (x *ThunderBrowser) Init(ctx context.Context) (err error) {
if x.XunLeiBrowserCommon == nil {
x.XunLeiBrowserCommon = &XunLeiBrowserCommon{
Common: &Common{
client: base.NewRestyClient(),
Algorithms: []string{
"x+I5XiTByg",
"6QU1x5DqGAV3JKg6h",
"VI1vL1WXr7st0es",
"n+/3yhlrnKs4ewhLgZhZ5ITpt554",
"UOip2PE7BLIEov/ZX6VOnsz",
"Q70h9lpViNCOC8sGVkar9o22LhBTjfP",
"IVHFuB1JcMlaZHnW",
"bKE",
"HZRbwxOiQx+diNopi6Nu",
"fwyasXgYL3rP314331b",
"LWxXAiSW4",
"UlWIjv1HGrC6Ngmt4Nohx",
"FOa+Lc0bxTDpTwIh2",
"0+RY",
"xmRVMqokHHpvsiH0",
},
client: base.NewRestyClient(),
Algorithms: Algorithms,
DeviceID: utils.GetMD5EncodeStr(x.Username + x.Password),
ClientID: "ZUBzD9J_XPXfn7f7",
ClientSecret: "yESVmHecEe6F0aou69vl-g",
ClientVersion: "1.0.7.1938",
PackageName: "com.xunlei.browser",
UserAgent: "ANDROID-com.xunlei.browser/1.0.7.1938 netWorkType/5G appid/22062 deviceName/Xiaomi_M2004j7ac deviceModel/M2004J7AC OSVersion/12 protocolVersion/301 platformVersion/10 sdkVersion/233100 Oauth2Client/0.9 (Linux 4_14_186-perf-gddfs8vbb238b) (JAVA 0)",
DownloadUserAgent: "AndroidDownloadManager/12 (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), PackageName, SdkVersion, ClientVersion, PackageName),
DownloadUserAgent: DownloadUserAgent,
UseVideoUrl: x.UseVideoUrl,

RemoveWay: x.Addition.RemoveWay,
refreshCTokenCk: func(token string) {
x.CaptchaToken = token
op.MustSaveDriverStorage(x)
Expand Down Expand Up @@ -107,6 +91,9 @@ func (x *ThunderBrowser) Init(ctx context.Context) (err error) {
if ctoekn != "" {
x.SetCaptchaToken(ctoekn)
}
if x.DeviceID == "" {
x.SetDeviceID(utils.GetMD5EncodeStr(x.Username + x.Password))
}
x.XunLeiBrowserCommon.UseVideoUrl = x.UseVideoUrl
x.Addition.RootFolderID = x.RootFolderID
// 防止重复登录
Expand Down Expand Up @@ -170,30 +157,58 @@ func (x *ThunderBrowserExpert) Init(ctx context.Context) (err error) {
x.XunLeiBrowserCommon = &XunLeiBrowserCommon{
Common: &Common{
client: base.NewRestyClient(),

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), x.PackageName, SdkVersion, x.ClientVersion, x.PackageName)
}
return BuildCustomUserAgent(utils.GetMD5EncodeStr(x.ExpertAddition.RefreshToken), x.PackageName, SdkVersion, x.ClientVersion, x.PackageName)
}(),
DownloadUserAgent: func() string {
if x.ExpertAddition.DownloadUserAgent != "" {
return x.ExpertAddition.DownloadUserAgent
}
return DownloadUserAgent
}(),
UseVideoUrl: x.UseVideoUrl,
RemoveWay: x.ExpertAddition.RemoveWay,
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.UserAgent != "" {
x.ExpertAddition.UserAgent = x.Common.UserAgent
op.MustSaveDriverStorage(x)
}
if x.Common.DownloadUserAgent != "" {
x.ExpertAddition.DownloadUserAgent = x.Common.DownloadUserAgent
op.MustSaveDriverStorage(x)
}
x.XunLeiBrowserCommon.UseVideoUrl = x.UseVideoUrl
x.ExpertAddition.RootFolderID = x.RootFolderID
Expand Down Expand Up @@ -488,7 +503,8 @@ func (xc *XunLeiBrowserCommon) Remove(ctx context.Context, obj model.Obj) error
}
}

if xc.RemoveWay == "delete" && obj.GetPath() == ThunderDriveFileID {
// 先判断是否是特殊情况
if obj.GetPath() == ThunderDriveFileID {
_, err := xc.Request(FILE_API_URL+"/{fileID}/trash", http.MethodPatch, func(r *resty.Request) {
r.SetContext(ctx)
r.SetPathParam("fileID", obj.GetID())
Expand All @@ -503,12 +519,20 @@ func (xc *XunLeiBrowserCommon) Remove(ctx context.Context, obj model.Obj) error
return err
}

_, err := xc.Request(FILE_API_URL+":batchTrash", http.MethodPost, func(r *resty.Request) {
r.SetContext(ctx)
r.SetBody(&js)
}, nil)
return err

// 根据用户选择的删除方式进行删除
if xc.RemoveWay == "delete" {
_, err := xc.Request(FILE_API_URL+":batchDelete", http.MethodPost, func(r *resty.Request) {
r.SetContext(ctx)
r.SetBody(&js)
}, nil)
return err
} else {
_, err := xc.Request(FILE_API_URL+":batchTrash", http.MethodPost, func(r *resty.Request) {
r.SetContext(ctx)
r.SetBody(&js)
}, nil)
return err
}
}

func (xc *XunLeiBrowserCommon) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
Expand Down Expand Up @@ -756,7 +780,7 @@ func (xc *XunLeiBrowserCommon) RefreshToken(refreshToken string) (*TokenResp, er
}

if resp.RefreshToken == "" {
return nil, errs.EmptyToken
return nil, errors.New("refresh token is empty")
}
return &resp, nil
}
Expand All @@ -775,7 +799,7 @@ func (xc *XunLeiBrowserCommon) GetSafeAccessToken(safePassword string) (string,
}

if resp.Token == "" {
return "", errs.EmptyToken
return "", errors.New("SafePassword is incorrect ")
}
return resp.Token, nil
}
Expand Down
20 changes: 10 additions & 10 deletions drivers/thunder_browser/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ type ExpertAddition struct {
SignType string `json:"sign_type" type:"select" options:"algorithms,captcha_sign" default:"algorithms"`

// 登录方式1
Username string `json:"username" required:"true" help:"login type is user,this is required"`
Password string `json:"password" required:"true" help:"login type is user,this is required"`
SafePassword string `json:"safe_password" required:"false" help:"login type is user,this is required"` // 超级保险箱密码
Username string `json:"username" required:"true" help:"login type is user,this is required"`
Password string `json:"password" required:"true" help:"login type is user,this is required"`
// 登录方式2
RefreshToken string `json:"refresh_token" required:"true" help:"login type is refresh_token,this is required"`

SafePassword string `json:"safe_password" required:"true" help:"super safe password"` // 超级保险箱密码

// 签名方法1
Algorithms string `json:"algorithms" required:"true" help:"sign type is algorithms,this is required" default:"x+I5XiTByg,6QU1x5DqGAV3JKg6h,VI1vL1WXr7st0es,n+/3yhlrnKs4ewhLgZhZ5ITpt554,UOip2PE7BLIEov/ZX6VOnsz,Q70h9lpViNCOC8sGVkar9o22LhBTjfP,IVHFuB1JcMlaZHnW,bKE,HZRbwxOiQx+diNopi6Nu,fwyasXgYL3rP314331b,LWxXAiSW4,UlWIjv1HGrC6Ngmt4Nohx,FOa+Lc0bxTDpTwIh2,0+RY,xmRVMqokHHpvsiH0"`
Algorithms string `json:"algorithms" required:"true" help:"sign type is algorithms,this is required" default:"p+ExqPV,LwdwKlprzv7cQBQmxN5,vc08P1NwUBnbGsl58LzTW,VVNeXaXmZ8HH1SJEnp6YpVFSFU,pNAOJ,CNChvyDehAmUR1TDodfOusBAx,MS98NnX4Np8nxvEh6Ulv+SMMKMzKvD34C7lGWbb,9MpFF21GnVOYku0NM9Y/hzsK471UCUZ2o+,EY1QfeA06fXlw9wZNoZaXEED5zZPvNWI,,sciE,FIPqgQDUUW1e0GkiBFd5w7mCQ,zW,75XFdEO0Gi"`
// 签名方法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 @@ -33,15 +34,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:"ZUBzD9J_XPXfn7f7"`
ClientSecret string `json:"client_secret" required:"true" default:"yESVmHecEe6F0aou69vl-g"`
ClientVersion string `json:"client_version" required:"true" default:"1.0.7.1938"`
ClientVersion string `json:"client_version" required:"true" default:"1.0.8.2215"`
PackageName string `json:"package_name" required:"true" default:"com.xunlei.browser"`

// 不影响登录,影响下载速度
UserAgent string `json:"user_agent" required:"true" default:"ANDROID-com.xunlei.browser/1.0.7.1938 netWorkType/5G appid/22062 deviceName/Xiaomi_M2004j7ac deviceModel/M2004J7AC OSVersion/12 protocolVersion/301 platformVersion/10 sdkVersion/233100 Oauth2Client/0.9 (Linux 4_14_186-perf-gddfs8vbb238b) (JAVA 0)"`
DownloadUserAgent string `json:"download_user_agent" required:"true" default:"AndroidDownloadManager/12 (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 @@ -76,7 +77,7 @@ type Addition struct {
driver.RootID
Username string `json:"username" required:"true"`
Password string `json:"password" required:"true"`
SafePassword string `json:"safe_password" required:"false"` // 超级保险箱密码
SafePassword string `json:"safe_password" required:"true"` // 超级保险箱密码
CaptchaToken string `json:"captcha_token"`
UseVideoUrl bool `json:"use_video_url" default:"false"`
RemoveWay string `json:"remove_way" required:"true" type:"select" options:"trash,delete"`
Expand All @@ -90,7 +91,6 @@ func (i *Addition) GetIdentity() string {
var config = driver.Config{
Name: "ThunderBrowser",
LocalSort: true,
OnlyProxy: true,
}

var configExpert = driver.Config{
Expand Down
69 changes: 69 additions & 0 deletions drivers/thunder_browser/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io"
"net/http"
"regexp"
"strings"
"time"

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

var Algorithms = []string{
"p+ExqPV",
"LwdwKlprzv7cQBQmxN5",
"vc08P1NwUBnbGsl58LzTW",
"VVNeXaXmZ8HH1SJEnp6YpVFSFU",
"pNAOJ",
"CNChvyDehAmUR1TDodfOusBAx",
"MS98NnX4Np8nxvEh6Ulv+SMMKMzKvD34C7lGWbb",
"9MpFF21GnVOYku0NM9Y/hzsK471UCUZ2o+",
"EY1QfeA06fXlw9wZNoZaXEED5zZPvNWI",
"",
"sciE",
"FIPqgQDUUW1e0GkiBFd5w7mCQ",
"zW",
"75XFdEO0Gi",
}

const (
ClientID = "ZUBzD9J_XPXfn7f7"
ClientSecret = "yESVmHecEe6F0aou69vl-g"
ClientVersion = "1.0.8.2215"
PackageName = "com.xunlei.browser"
DownloadUserAgent = "AndroidDownloadManager/13 (Linux; U; Android 13; M2004J7AC Build/SP1A.210812.016)"
SdkVersion = "2.0.3.262"
)

const (
FOLDER = "drive#folder"
FILE = "drive#file"
Expand Down Expand Up @@ -74,6 +101,10 @@ type Common struct {
refreshCTokenCk func(token string)
}

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

func (c *Common) SetCaptchaToken(captchaToken string) {
c.captchaToken = captchaToken
}
Expand Down Expand Up @@ -247,3 +278,41 @@ func EncryptPassword(password string) string {
// 将哈希值转换为十六进制字符串
return hex.EncodeToString(hash[:])
}

func generateDeviceSign(deviceID, packageName string) string {

signatureBase := fmt.Sprintf("%s%s%s%s", deviceID, packageName, "22062", "a5d7416858147a4ab99573872ffccef8")

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, appName, sdkVersion, clientVersion, packageName string) string {
//deviceSign := generateDeviceSign(deviceID, packageName)
var sb strings.Builder

sb.WriteString(fmt.Sprintf("ANDROID-%s/%s ", appName, clientVersion))
sb.WriteString("networkType/WIFI ")
sb.WriteString(fmt.Sprintf("appid/%s ", "22062"))
sb.WriteString(fmt.Sprintf("deviceName/Xiaomi_M2004j7ac "))
sb.WriteString(fmt.Sprintf("deviceModel/M2004J7AC "))
sb.WriteString(fmt.Sprintf("OSVersion/13 "))
sb.WriteString(fmt.Sprintf("protocolVersion/301 "))
sb.WriteString(fmt.Sprintf("platformversion/10 "))
sb.WriteString(fmt.Sprintf("sdkVersion/%s ", sdkVersion))
sb.WriteString(fmt.Sprintf("Oauth2Client/0.9 (Linux 4_9_337-perf-sn-uotan-gd9d488809c3d) (JAVA 0) "))
return sb.String()
}

0 comments on commit 316f356

Please sign in to comment.