From badc4559996b134b1282d051613cf7e37ea89ae6 Mon Sep 17 00:00:00 2001 From: YangXu <2945065490@qq.com> Date: Sat, 28 Sep 2024 21:52:50 +0800 Subject: [PATCH 1/6] feat(123&123share): Android Or TV --- drivers/123/driver.go | 20 ++++ drivers/123/meta.go | 7 +- drivers/123/util.go | 186 ++++++++++++++++++------------------ drivers/123_share/driver.go | 24 ++++- drivers/123_share/meta.go | 7 +- drivers/123_share/util.go | 61 ++++++++++-- 6 files changed, 200 insertions(+), 105 deletions(-) diff --git a/drivers/123/driver.go b/drivers/123/driver.go index 3620431d9b3..232fc00917e 100644 --- a/drivers/123/driver.go +++ b/drivers/123/driver.go @@ -30,6 +30,7 @@ type Pan123 struct { model.Storage Addition apiRateLimit sync.Map + params Params } func (d *Pan123) Config() driver.Config { @@ -41,6 +42,25 @@ func (d *Pan123) GetAddition() driver.Additional { } func (d *Pan123) Init(ctx context.Context) error { + // 拼接UserAgent + if d.PlatformType == "android" { + d.params.UserAgent = AndroidUserAgentPrefix + "(" + d.OsVersion + ";" + d.DeviceName + " " + d.DeiveType + ")" + d.params.Platform = AndroidPlatformParam + d.params.AppVersion = AndroidAppVer + d.params.XChannel = AndroidXChannel + d.params.XAppVersion = AndroidXAppVer + + } else if d.PlatformType == "tv" { + d.params.UserAgent = TVUserAgentPrefix + "(" + d.OsVersion + ";" + d.DeviceName + " " + d.DeiveType + ")" + d.params.Platform = TVPlatformParam + d.params.AppVersion = TVAndroidAppVer + } + + d.params.OsVersion = d.OsVersion + d.params.LoginUuid = d.LoginUuid + d.params.DeviceName = d.DeviceName + d.params.DeviceType = d.DeiveType + _, err := d.request(UserInfo, http.MethodGet, nil, nil) return err } diff --git a/drivers/123/meta.go b/drivers/123/meta.go index cb2cbc15ba0..4d67284cab0 100644 --- a/drivers/123/meta.go +++ b/drivers/123/meta.go @@ -11,7 +11,12 @@ type Addition struct { driver.RootID //OrderBy string `json:"order_by" type:"select" options:"file_id,file_name,size,update_at" default:"file_name"` //OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"` - AccessToken string + AccessToken string `json:"accesstoken" type:"text"` + PlatformType string `json:"platformType" type:"select" options:"android,tv" default:"android" required:"true"` + DeviceName string `json:"devicename" default:"XiaoMi"` + DeiveType string `json:"devicetype" default:"houji"` + OsVersion string `json:"osversion" default:"14"` + LoginUuid string `json:"loginuuid" default:"1fce20b2428d30899fd537f4cf231dfb"` } var config = driver.Config{ diff --git a/drivers/123/util.go b/drivers/123/util.go index 6365b1c9a1e..c04dddbe590 100644 --- a/drivers/123/util.go +++ b/drivers/123/util.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/google/uuid" "hash/crc32" "math" "math/rand" @@ -27,7 +28,7 @@ const ( AApi = "https://www.123pan.com/a/api" BApi = "https://www.123pan.com/b/api" LoginApi = "https://login.123pan.com/api" - MainApi = BApi + MainApi = Api SignIn = LoginApi + "/user/sign_in" Logout = MainApi + "/user/logout" UserInfo = MainApi + "/user/info" @@ -46,6 +47,29 @@ const ( //AuthKeySalt = "8-8D$sL8gPjom7bk#cY" ) +const ( + AndroidUserAgentPrefix = "123pan/v2.4.7" // 123pan/v2.4.7(Android_14;XiaoMi) + AndroidPlatformParam = "android" + AndroidAppVer = "69" + AndroidXAppVer = "2.4.7" + AndroidXChannel = "1002" + TVUserAgentPrefix = "123pan_android_tv/1.0.0" // 123pan_android_tv/1.0.0(14;samsung SM-X800) + TVPlatformParam = "android_tv" + TVAndroidAppVer = "100" +) + +type Params struct { + UserAgent string + Platform string + AppVersion string + OsVersion string + LoginUuid string + DeviceType string + DeviceName string + XChannel string + XAppVersion string +} + func signPath(path string, os string, version string) (k string, v string) { table := []byte{'a', 'd', 'e', 'f', 'g', 'h', 'l', 'm', 'y', 'i', 'j', 'n', 'o', 'p', 'k', 'q', 'r', 's', 't', 'u', 'b', 'c', 'v', 'w', 's', 'z'} random := fmt.Sprintf("%.f", math.Round(1e7*rand.Float64())) @@ -69,81 +93,6 @@ func GetApi(rawUrl string) string { return u.String() } -//func GetApi(url string) string { -// vm := js.New() -// vm.Set("url", url[22:]) -// r, err := vm.RunString(` -// (function(e){ -// function A(t, e) { -// e = 1 < arguments.length && void 0 !== e ? e : 10; -// for (var n = function() { -// for (var t = [], e = 0; e < 256; e++) { -// for (var n = e, r = 0; r < 8; r++) -// n = 1 & n ? 3988292384 ^ n >>> 1 : n >>> 1; -// t[e] = n -// } -// return t -// }(), r = function(t) { -// t = t.replace(/\\r\\n/g, "\\n"); -// for (var e = "", n = 0; n < t.length; n++) { -// var r = t.charCodeAt(n); -// r < 128 ? e += String.fromCharCode(r) : e = 127 < r && r < 2048 ? (e += String.fromCharCode(r >> 6 | 192)) + String.fromCharCode(63 & r | 128) : (e = (e += String.fromCharCode(r >> 12 | 224)) + String.fromCharCode(r >> 6 & 63 | 128)) + String.fromCharCode(63 & r | 128) -// } -// return e -// }(t), a = -1, i = 0; i < r.length; i++) -// a = a >>> 8 ^ n[255 & (a ^ r.charCodeAt(i))]; -// return (a = (-1 ^ a) >>> 0).toString(e) -// } -// -// function v(t) { -// return (v = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) { -// return typeof t -// } -// : function(t) { -// return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t -// } -// )(t) -// } -// -// for (p in a = Math.round(1e7 * Math.random()), -// o = Math.round(((new Date).getTime() + 60 * (new Date).getTimezoneOffset() * 1e3 + 288e5) / 1e3).toString(), -// m = ["a", "d", "e", "f", "g", "h", "l", "m", "y", "i", "j", "n", "o", "p", "k", "q", "r", "s", "t", "u", "b", "c", "v", "w", "s", "z"], -// u = function(t, e, n) { -// var r; -// n = 2 < arguments.length && void 0 !== n ? n : 8; -// return 0 === arguments.length ? null : (r = "object" === v(t) ? t : (10 === "".concat(t).length && (t = 1e3 * Number.parseInt(t)), -// new Date(t)), -// t += 6e4 * new Date(t).getTimezoneOffset(), -// { -// y: (r = new Date(t + 36e5 * n)).getFullYear(), -// m: r.getMonth() + 1 < 10 ? "0".concat(r.getMonth() + 1) : r.getMonth() + 1, -// d: r.getDate() < 10 ? "0".concat(r.getDate()) : r.getDate(), -// h: r.getHours() < 10 ? "0".concat(r.getHours()) : r.getHours(), -// f: r.getMinutes() < 10 ? "0".concat(r.getMinutes()) : r.getMinutes() -// }) -// }(o), -// h = u.y, -// g = u.m, -// l = u.d, -// c = u.h, -// u = u.f, -// d = [h, g, l, c, u].join(""), -// f = [], -// d) -// f.push(m[Number(d[p])]); -// return h = A(f.join("")), -// g = A("".concat(o, "|").concat(a, "|").concat(e, "|").concat("web", "|").concat("3", "|").concat(h)), -// "".concat(h, "=").concat(o, "-").concat(a, "-").concat(g); -// })(url) -// `) -// if err != nil { -// fmt.Println(err) -// return url -// } -// v, _ := r.Export().(string) -// return url + "?" + v -//} - func (d *Pan123) login() error { var body base.Json if utils.IsEmailFormat(d.Username) { @@ -156,19 +105,47 @@ func (d *Pan123) login() error { body = base.Json{ "passport": d.Username, "password": d.Password, - "remember": true, + "type": 1, } } - res, err := base.RestyClient.R(). - SetHeaders(map[string]string{ - "origin": "https://www.123pan.com", - "referer": "https://www.123pan.com/", - "user-agent": "Dart/2.19(dart:io)-alist", - "platform": "web", - "app-version": "3", - //"user-agent": base.UserAgent, - }). - SetBody(body).Post(SignIn) + + req := base.RestyClient.R() + + req.SetHeaders(map[string]string{ + /* "origin": "https://www.123pan.com", + "referer": "https://www.123pan.com/",*/ + "user-agent": d.params.UserAgent, + "platform": d.params.Platform, + "app-version": d.params.AppVersion, + "osversion": d.params.OsVersion, + "devicetype": d.params.DeviceType, + "devicename": d.params.DeviceName, + "loginuuid": d.params.LoginUuid, + }) + + if d.params.XChannel != "" && d.params.XAppVersion != "" { + req.SetHeaders(map[string]string{ + "x-channel": d.params.XChannel, + "x-app-version": d.params.XAppVersion, + }) + } + + req.SetQueryParam("auth-key", generateAuthKey()) + + res, err := req.SetBody(body).Post(SignIn) + //res, err := base.RestyClient.R(). + // SetHeaders(map[string]string{ + // /* "origin": "https://www.123pan.com", + // "referer": "https://www.123pan.com/",*/ + // "user-agent": d.params.UserAgent, + // "platform": d.params.Platform, + // "app-version": d.params.AppVersion, + // "osversion": d.params.OsVersion, + // "devicetype": d.params.DeviceType, + // "devicename": d.params.DeviceName, + // //"user-agent": base.UserAgent, + // }). + // SetBody(body).Post(SignIn) if err != nil { return err } @@ -197,14 +174,27 @@ func (d *Pan123) login() error { func (d *Pan123) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { req := base.RestyClient.R() req.SetHeaders(map[string]string{ - "origin": "https://www.123pan.com", - "referer": "https://www.123pan.com/", + /* "origin": "https://www.123pan.com", + "referer": "https://www.123pan.com/",*/ "authorization": "Bearer " + d.AccessToken, - "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) alist-client", - "platform": "web", - "app-version": "3", - //"user-agent": base.UserAgent, + "user-agent": d.params.UserAgent, + "platform": d.params.Platform, + "app-version": d.params.AppVersion, + "osversion": d.params.OsVersion, + "devicetype": d.params.DeviceType, + "devicename": d.params.DeviceName, + "loginuuid": d.params.LoginUuid, }) + + if d.params.XChannel != "" && d.params.XAppVersion != "" { + req.SetHeaders(map[string]string{ + "x-channel": d.params.XChannel, + "x-app-version": d.params.XAppVersion, + }) + } + + req.SetQueryParam("auth-key", generateAuthKey()) + if callback != nil { callback(req) } @@ -216,7 +206,8 @@ func (d *Pan123) request(url string, method string, callback base.ReqCallback, r // return nil, err //} //req.SetQueryParam("auth-key", *authKey) - res, err := req.Execute(method, GetApi(url)) + //res, err := req.Execute(method, GetApi(url)) + res, err := req.Execute(method, url) if err != nil { return nil, err } @@ -279,3 +270,10 @@ func (d *Pan123) getFiles(ctx context.Context, parentId string, name string) ([] } return res, nil } + +func generateAuthKey() string { + timestamp := time.Now().Unix() + randomInt := rand.Intn(1e9) // 生成9位的随机整数 + uuidStr := strings.ReplaceAll(uuid.New().String(), "-", "") // 去掉 UUID 中的所有 - + return fmt.Sprintf("%d-%09d-%s", timestamp, randomInt, uuidStr) // 确保随机整数是9位 +} diff --git a/drivers/123_share/driver.go b/drivers/123_share/driver.go index 9c1f3803710..664cbf254e6 100644 --- a/drivers/123_share/driver.go +++ b/drivers/123_share/driver.go @@ -23,6 +23,7 @@ type Pan123Share struct { model.Storage Addition apiRateLimit sync.Map + params Params } func (d *Pan123Share) Config() driver.Config { @@ -36,6 +37,25 @@ func (d *Pan123Share) GetAddition() driver.Additional { func (d *Pan123Share) Init(ctx context.Context) error { // TODO login / refresh token //op.MustSaveDriverStorage(d) + // 拼接UserAgent + if d.PlatformType == "android" { + d.params.UserAgent = AndroidUserAgentPrefix + "(" + d.OsVersion + ";" + d.DeviceName + " " + d.DeiveType + ")" + d.params.Platform = AndroidPlatformParam + d.params.AppVersion = AndroidAppVer + d.params.XChannel = AndroidXChannel + d.params.XAppVersion = AndroidXAppVer + + } else if d.PlatformType == "tv" { + d.params.UserAgent = TVUserAgentPrefix + "(" + d.OsVersion + ";" + d.DeviceName + " " + d.DeiveType + ")" + d.params.Platform = TVPlatformParam + d.params.AppVersion = TVAndroidAppVer + } + + d.params.OsVersion = d.OsVersion + d.params.LoginUuid = d.LoginUuid + d.params.DeviceName = d.DeviceName + d.params.DeviceType = d.DeiveType + return nil } @@ -66,11 +86,13 @@ func (d *Pan123Share) Link(ctx context.Context, file model.Obj, args model.LinkA } } data := base.Json{ + "driveId": "0", "shareKey": d.ShareKey, "SharePwd": d.SharePwd, "etag": f.Etag, "fileId": f.FileId, "s3keyFlag": f.S3KeyFlag, + "FileName": f.FileName, "size": f.Size, } resp, err := d.request(DownloadInfo, http.MethodPost, func(req *resty.Request) { @@ -152,7 +174,7 @@ func (d *Pan123Share) Put(ctx context.Context, dstDir model.Obj, stream model.Fi func (d *Pan123Share) APIRateLimit(ctx context.Context, api string) error { value, _ := d.apiRateLimit.LoadOrStore(api, - rate.NewLimiter(rate.Every(700*time.Millisecond), 1)) + rate.NewLimiter(rate.Every(800*time.Millisecond), 1)) limiter := value.(*rate.Limiter) return limiter.Wait(ctx) diff --git a/drivers/123_share/meta.go b/drivers/123_share/meta.go index 7cbcba27724..48bd2357f10 100644 --- a/drivers/123_share/meta.go +++ b/drivers/123_share/meta.go @@ -11,7 +11,12 @@ type Addition struct { driver.RootID //OrderBy string `json:"order_by" type:"select" options:"file_name,size,update_at" default:"file_name"` //OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"` - AccessToken string `json:"accesstoken" type:"text"` + AccessToken string `json:"accesstoken" type:"text" required:"true"` + PlatformType string `json:"platformType" type:"select" options:"android,tv" default:"android" required:"true"` + DeviceName string `json:"devicename" default:"XiaoMi"` + DeiveType string `json:"devicetype" default:"houji"` + OsVersion string `json:"osversion" default:"14"` + LoginUuid string `json:"loginuuid" default:"1fce20b2428d30899fd537f4cf231dfb"` } var config = driver.Config{ diff --git a/drivers/123_share/util.go b/drivers/123_share/util.go index 80ea8f0ca46..a7e3e5045be 100644 --- a/drivers/123_share/util.go +++ b/drivers/123_share/util.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/google/uuid" "hash/crc32" "math" "math/rand" @@ -23,12 +24,35 @@ const ( Api = "https://www.123pan.com/api" AApi = "https://www.123pan.com/a/api" BApi = "https://www.123pan.com/b/api" - MainApi = BApi + MainApi = Api FileList = MainApi + "/share/get" DownloadInfo = MainApi + "/share/download/info" //AuthKeySalt = "8-8D$sL8gPjom7bk#cY" ) +const ( + AndroidUserAgentPrefix = "123pan/v2.4.7" // 123pan/v2.4.7(Android_14;XiaoMi) + AndroidPlatformParam = "android" + AndroidAppVer = "69" + AndroidXAppVer = "2.4.7" + AndroidXChannel = "1002" + TVUserAgentPrefix = "123pan_android_tv/1.0.0" // 123pan_android_tv/1.0.0(14;samsung SM-X800) + TVPlatformParam = "android_tv" + TVAndroidAppVer = "100" +) + +type Params struct { + UserAgent string + Platform string + AppVersion string + OsVersion string + LoginUuid string + DeviceType string + DeviceName string + XChannel string + XAppVersion string +} + func signPath(path string, os string, version string) (k string, v string) { table := []byte{'a', 'd', 'e', 'f', 'g', 'h', 'l', 'm', 'y', 'i', 'j', 'n', 'o', 'p', 'k', 'q', 'r', 's', 't', 'u', 'b', 'c', 'v', 'w', 's', 'z'} random := fmt.Sprintf("%.f", math.Round(1e7*rand.Float64())) @@ -55,21 +79,35 @@ func GetApi(rawUrl string) string { func (d *Pan123Share) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { req := base.RestyClient.R() req.SetHeaders(map[string]string{ - "origin": "https://www.123pan.com", - "referer": "https://www.123pan.com/", + /* "origin": "https://www.123pan.com", + "referer": "https://www.123pan.com/",*/ "authorization": "Bearer " + d.AccessToken, - "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) alist-client", - "platform": "web", - "app-version": "3", - //"user-agent": base.UserAgent, + "user-agent": d.params.UserAgent, + "platform": d.params.Platform, + "app-version": d.params.AppVersion, + "osversion": d.params.OsVersion, + "devicetype": d.params.DeviceType, + "devicename": d.params.DeviceName, + "loginuuid": d.params.LoginUuid, }) + + if d.params.XChannel != "" && d.params.XAppVersion != "" { + req.SetHeaders(map[string]string{ + "x-channel": d.params.XChannel, + "x-app-version": d.params.XAppVersion, + }) + } + + req.SetQueryParam("auth-key", generateAuthKey()) + if callback != nil { callback(req) } if resp != nil { req.SetResult(resp) } - res, err := req.Execute(method, GetApi(url)) + //res, err := req.Execute(method, GetApi(url)) + res, err := req.Execute(method, url) if err != nil { return nil, err } @@ -115,3 +153,10 @@ func (d *Pan123Share) getFiles(ctx context.Context, parentId string) ([]File, er } // do others that not defined in Driver interface + +func generateAuthKey() string { + timestamp := time.Now().Unix() + randomInt := rand.Intn(1e9) // 生成9位的随机整数 + uuidStr := strings.ReplaceAll(uuid.New().String(), "-", "") // 去掉 UUID 中的所有 - + return fmt.Sprintf("%d-%09d-%s", timestamp, randomInt, uuidStr) // 确保随机整数是9位 +} From 05d9e2d6ab3035ad5ba9f43ee1d45f46e2c26135 Mon Sep 17 00:00:00 2001 From: xrgzs Date: Fri, 4 Oct 2024 20:56:05 +0800 Subject: [PATCH 2/6] fix(123&123share): update default values for device-related fields - Update DeviceName to "Xiaomi" - Change DeiveType to "M1810E5A" - Update OsVersion to "Android_8.1.0" - Modify LoginUuid to "66a4c82756134af2a57d323fd7a5e58c" - Remove required attribute from AccessToken in 123_share/meta.go --- drivers/123/meta.go | 8 ++++---- drivers/123_share/meta.go | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/123/meta.go b/drivers/123/meta.go index 4d67284cab0..961497d4292 100644 --- a/drivers/123/meta.go +++ b/drivers/123/meta.go @@ -13,10 +13,10 @@ type Addition struct { //OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"` AccessToken string `json:"accesstoken" type:"text"` PlatformType string `json:"platformType" type:"select" options:"android,tv" default:"android" required:"true"` - DeviceName string `json:"devicename" default:"XiaoMi"` - DeiveType string `json:"devicetype" default:"houji"` - OsVersion string `json:"osversion" default:"14"` - LoginUuid string `json:"loginuuid" default:"1fce20b2428d30899fd537f4cf231dfb"` + DeviceName string `json:"devicename" default:"Xiaomi"` + DeiveType string `json:"devicetype" default:"M1810E5A"` + OsVersion string `json:"osversion" default:"Android_8.1.0"` + LoginUuid string `json:"loginuuid" default:"66a4c82756134af2a57d323fd7a5e58c"` } var config = driver.Config{ diff --git a/drivers/123_share/meta.go b/drivers/123_share/meta.go index 48bd2357f10..bb7f259f631 100644 --- a/drivers/123_share/meta.go +++ b/drivers/123_share/meta.go @@ -11,12 +11,12 @@ type Addition struct { driver.RootID //OrderBy string `json:"order_by" type:"select" options:"file_name,size,update_at" default:"file_name"` //OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"` - AccessToken string `json:"accesstoken" type:"text" required:"true"` + AccessToken string `json:"accesstoken" type:"text"` PlatformType string `json:"platformType" type:"select" options:"android,tv" default:"android" required:"true"` - DeviceName string `json:"devicename" default:"XiaoMi"` - DeiveType string `json:"devicetype" default:"houji"` - OsVersion string `json:"osversion" default:"14"` - LoginUuid string `json:"loginuuid" default:"1fce20b2428d30899fd537f4cf231dfb"` + DeviceName string `json:"devicename" default:"Xiaomi"` + DeiveType string `json:"devicetype" default:"M1810E5A"` + OsVersion string `json:"osversion" default:"Android_8.1.0"` + LoginUuid string `json:"loginuuid" default:"66a4c82756134af2a57d323fd7a5e58c"` } var config = driver.Config{ From 5d4cf4ab373a939ab521dc9c6877ea1b93dcef5e Mon Sep 17 00:00:00 2001 From: xrgzs Date: Fri, 4 Oct 2024 21:22:42 +0800 Subject: [PATCH 3/6] fix(123): adjust API rate limit to 800ms Increase the rate limit for Pan123 API calls from 700ms to 800ms to comply with the API's rate limit requirements. This adjustment ensures that the driver operates within the allowed limits and avoids potential service disruptions. --- drivers/123/driver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/123/driver.go b/drivers/123/driver.go index 232fc00917e..9b5545d8d19 100644 --- a/drivers/123/driver.go +++ b/drivers/123/driver.go @@ -278,7 +278,7 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr func (d *Pan123) APIRateLimit(ctx context.Context, api string) error { value, _ := d.apiRateLimit.LoadOrStore(api, - rate.NewLimiter(rate.Every(700*time.Millisecond), 1)) + rate.NewLimiter(rate.Every(800*time.Millisecond), 1)) limiter := value.(*rate.Limiter) return limiter.Wait(ctx) From 797d69c20bb005ef190ad46ac5834419dd35f430 Mon Sep 17 00:00:00 2001 From: xrgzs Date: Fri, 4 Oct 2024 21:54:16 +0800 Subject: [PATCH 4/6] fix(123&123share): remove X-Forwarded-For header --- drivers/123/driver.go | 10 +--------- drivers/123_share/driver.go | 9 +-------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/123/driver.go b/drivers/123/driver.go index 9b5545d8d19..7bfe14421c4 100644 --- a/drivers/123/driver.go +++ b/drivers/123/driver.go @@ -85,13 +85,6 @@ func (d *Pan123) List(ctx context.Context, dir model.Obj, args model.ListArgs) ( func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { if f, ok := file.(File); ok { //var resp DownResp - var headers map[string]string - if !utils.IsLocalIPAddr(args.IP) { - headers = map[string]string{ - //"X-Real-IP": "1.1.1.1", - "X-Forwarded-For": args.IP, - } - } data := base.Json{ "driveId": 0, "etag": f.Etag, @@ -102,8 +95,7 @@ func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs) "type": f.Type, } resp, err := d.request(DownloadInfo, http.MethodPost, func(req *resty.Request) { - - req.SetBody(data).SetHeaders(headers) + req.SetBody(data) }, nil) if err != nil { return nil, err diff --git a/drivers/123_share/driver.go b/drivers/123_share/driver.go index 664cbf254e6..17f21093738 100644 --- a/drivers/123_share/driver.go +++ b/drivers/123_share/driver.go @@ -78,13 +78,6 @@ func (d *Pan123Share) Link(ctx context.Context, file model.Obj, args model.LinkA // TODO return link of file, required if f, ok := file.(File); ok { //var resp DownResp - var headers map[string]string - if !utils.IsLocalIPAddr(args.IP) { - headers = map[string]string{ - //"X-Real-IP": "1.1.1.1", - "X-Forwarded-For": args.IP, - } - } data := base.Json{ "driveId": "0", "shareKey": d.ShareKey, @@ -96,7 +89,7 @@ func (d *Pan123Share) Link(ctx context.Context, file model.Obj, args model.LinkA "size": f.Size, } resp, err := d.request(DownloadInfo, http.MethodPost, func(req *resty.Request) { - req.SetBody(data).SetHeaders(headers) + req.SetBody(data) }, nil) if err != nil { return nil, err From a0459bd17423ddabb2bea538f2f494a4985f56f0 Mon Sep 17 00:00:00 2001 From: YangXu <2945065490@qq.com> Date: Mon, 7 Oct 2024 11:05:24 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat(123&123share):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=89=AB=E7=A0=81=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drivers/123/meta.go | 6 +- drivers/123/types.go | 18 ++++ drivers/123/util.go | 78 +++++++++++++++- drivers/123_share/driver.go | 9 +- drivers/123_share/meta.go | 8 +- drivers/123_share/types.go | 18 ++++ drivers/123_share/util.go | 176 ++++++++++++++++++++++++++++++++++-- 7 files changed, 297 insertions(+), 16 deletions(-) diff --git a/drivers/123/meta.go b/drivers/123/meta.go index 961497d4292..4694f585776 100644 --- a/drivers/123/meta.go +++ b/drivers/123/meta.go @@ -6,8 +6,10 @@ import ( ) type Addition struct { - Username string `json:"username" required:"true"` - Password string `json:"password" required:"true"` + Username string `json:"username"` + Password string `json:"password"` + UseQrCodeLogin bool `json:"use_qr_code_login"` + UniID string `json:"uni_id"` driver.RootID //OrderBy string `json:"order_by" type:"select" options:"file_id,file_name,size,update_at" default:"file_name"` //OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"` diff --git a/drivers/123/types.go b/drivers/123/types.go index a8682c52fc9..81738676973 100644 --- a/drivers/123/types.go +++ b/drivers/123/types.go @@ -121,3 +121,21 @@ type S3PreSignedURLs struct { PreSignedUrls map[string]string `json:"presignedUrls"` } `json:"data"` } + +type QrCodeGenerateResp struct { + Data struct { + UniID string `json:"uniID"` + Url string `json:"url"` + } `json:"data"` +} + +type QrCodeResultResp struct { + Data struct { + Expire time.Time `json:"expire"` + LoginType int `json:"login_type"` + RefreshTokenExpireTime int `json:"refresh_token_expire_time"` + Token string `json:"token"` + LoginStatus int `json:"loginStatus"` + ScanPlatform int `json:"scanPlatform"` + } `json:"data"` +} diff --git a/drivers/123/util.go b/drivers/123/util.go index c04dddbe590..13c3c7de0c3 100644 --- a/drivers/123/util.go +++ b/drivers/123/util.go @@ -2,9 +2,12 @@ package _123 import ( "context" + "encoding/base64" "errors" "fmt" + "github.com/alist-org/alist/v3/internal/op" "github.com/google/uuid" + "github.com/skip2/go-qrcode" "hash/crc32" "math" "math/rand" @@ -45,6 +48,8 @@ const ( UploadCompleteV2 = MainApi + "/file/upload_complete/v2" S3Complete = MainApi + "/file/s3_complete_multipart_upload" //AuthKeySalt = "8-8D$sL8gPjom7bk#cY" + QrcodeGenerate = MainApi + "/user/qr-code/generate" + QrcodeResult = MainApi + "/user/qr-code/result" ) const ( @@ -171,6 +176,69 @@ func (d *Pan123) login() error { // return &authKey, nil //} +func (d *Pan123) loginByQrCode() error { + if d.Addition.UniID == "" { + uniID, err := d.generateQrCode() + if uniID == "" && err != nil { + return err + } else { + // 保存 uniID 用于 二维码登录 + d.Addition.UniID = uniID + op.MustSaveDriverStorage(d) + return err + } + } else { + token, err := d.getTokenByUniID() + if token == "" && err != nil { + return err + } else { + d.Addition.AccessToken = token + op.MustSaveDriverStorage(d) + return err + } + } +} + +func (d *Pan123) generateQrCode() (string, error) { + var resp QrCodeGenerateResp + _, err := d.request(QrcodeGenerate, http.MethodGet, nil, &resp) + if err != nil { + return "", err + } + // 拼接二维码链接 + qrUrl := fmt.Sprintf(resp.Data.Url+"?uniID=%s", resp.Data.UniID+"&source=123pan&type=login") + // 生成二维码 + qrBytes, _ := qrcode.Encode(qrUrl, qrcode.Medium, 256) + base64Bytes := base64.StdEncoding.EncodeToString(qrBytes) + // 展示二维码 + qrTemplate := ` + + + Or Click Here + ` + qrPage := fmt.Sprintf(qrTemplate, base64Bytes, qrUrl) + return resp.Data.UniID, fmt.Errorf("need verify: \n%s", qrPage) +} + +func (d *Pan123) getTokenByUniID() (string, error) { + var resp QrCodeResultResp + _, err := d.request(QrcodeResult, http.MethodGet, func(req *resty.Request) { + req.SetQueryParam("uniID", d.Addition.UniID) + }, &resp) + if err != nil { + return "", err + } + + if resp.Data.LoginStatus == 4 { + return "", errors.New("uniID expired") + } else if resp.Data.Token == "" && resp.Data.LoginStatus == 0 { + return "", errors.New("wait for scan qrcode") + } + + return resp.Data.Token, nil + +} + func (d *Pan123) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { req := base.RestyClient.R() req.SetHeaders(map[string]string{ @@ -213,13 +281,19 @@ func (d *Pan123) request(url string, method string, callback base.ReqCallback, r } body := res.Body() code := utils.Json.Get(body, "code").ToInt() - if code != 0 { - if code == 401 { + if code != 0 && code != 200 { + if code == 401 && d.Addition.UseQrCodeLogin == false { err := d.login() if err != nil { return nil, err } return d.request(url, method, callback, resp) + } else if code == 401 && d.Addition.UseQrCodeLogin == true { + err := d.loginByQrCode() + if err != nil { + return nil, err + } + return d.request(url, method, callback, resp) } return nil, errors.New(jsoniter.Get(body, "message").ToString()) } diff --git a/drivers/123_share/driver.go b/drivers/123_share/driver.go index 17f21093738..7f8b2541fca 100644 --- a/drivers/123_share/driver.go +++ b/drivers/123_share/driver.go @@ -35,8 +35,7 @@ func (d *Pan123Share) GetAddition() driver.Additional { } func (d *Pan123Share) Init(ctx context.Context) error { - // TODO login / refresh token - //op.MustSaveDriverStorage(d) + // TODO refresh token // 拼接UserAgent if d.PlatformType == "android" { d.params.UserAgent = AndroidUserAgentPrefix + "(" + d.OsVersion + ";" + d.DeviceName + " " + d.DeiveType + ")" @@ -56,10 +55,14 @@ func (d *Pan123Share) Init(ctx context.Context) error { d.params.DeviceName = d.DeviceName d.params.DeviceType = d.DeiveType - return nil + _, err := d.request(UserInfo, http.MethodGet, nil, nil) + return err } func (d *Pan123Share) Drop(ctx context.Context) error { + _, _ = d.request(Logout, http.MethodPost, func(req *resty.Request) { + req.SetBody(base.Json{}) + }, nil) return nil } diff --git a/drivers/123_share/meta.go b/drivers/123_share/meta.go index bb7f259f631..7da542395dd 100644 --- a/drivers/123_share/meta.go +++ b/drivers/123_share/meta.go @@ -6,8 +6,12 @@ import ( ) type Addition struct { - ShareKey string `json:"sharekey" required:"true"` - SharePwd string `json:"sharepassword"` + Username string `json:"username"` + Password string `json:"password"` + UseQrCodeLogin bool `json:"use_qr_code_login"` + UniID string `json:"uni_id"` + ShareKey string `json:"sharekey" required:"true"` + SharePwd string `json:"sharepassword"` driver.RootID //OrderBy string `json:"order_by" type:"select" options:"file_name,size,update_at" default:"file_name"` //OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"` diff --git a/drivers/123_share/types.go b/drivers/123_share/types.go index e8ca9e77440..af26c5d034f 100644 --- a/drivers/123_share/types.go +++ b/drivers/123_share/types.go @@ -97,3 +97,21 @@ type Files struct { // DownloadUrl string `json:"DownloadUrl"` // } `json:"data"` //} + +type QrCodeGenerateResp struct { + Data struct { + UniID string `json:"uniID"` + Url string `json:"url"` + } `json:"data"` +} + +type QrCodeResultResp struct { + Data struct { + Expire time.Time `json:"expire"` + LoginType int `json:"login_type"` + RefreshTokenExpireTime int `json:"refresh_token_expire_time"` + Token string `json:"token"` + LoginStatus int `json:"loginStatus"` + ScanPlatform int `json:"scanPlatform"` + } `json:"data"` +} diff --git a/drivers/123_share/util.go b/drivers/123_share/util.go index a7e3e5045be..87a6a89d846 100644 --- a/drivers/123_share/util.go +++ b/drivers/123_share/util.go @@ -2,9 +2,12 @@ package _123Share import ( "context" + "encoding/base64" "errors" "fmt" + "github.com/alist-org/alist/v3/internal/op" "github.com/google/uuid" + "github.com/skip2/go-qrcode" "hash/crc32" "math" "math/rand" @@ -21,12 +24,17 @@ import ( ) const ( - Api = "https://www.123pan.com/api" - AApi = "https://www.123pan.com/a/api" - BApi = "https://www.123pan.com/b/api" - MainApi = Api - FileList = MainApi + "/share/get" - DownloadInfo = MainApi + "/share/download/info" + Api = "https://www.123pan.com/api" + AApi = "https://www.123pan.com/a/api" + BApi = "https://www.123pan.com/b/api" + MainApi = Api + SignIn = MainApi + "/user/sign_in" + Logout = MainApi + "/user/logout" + FileList = MainApi + "/share/get" + DownloadInfo = MainApi + "/share/download/info" + UserInfo = MainApi + "/user/info" + QrcodeGenerate = MainApi + "/user/qr-code/generate" + QrcodeResult = MainApi + "/user/qr-code/result" //AuthKeySalt = "8-8D$sL8gPjom7bk#cY" ) @@ -53,6 +61,147 @@ type Params struct { XAppVersion string } +func (d *Pan123Share) login() error { + var body base.Json + if utils.IsEmailFormat(d.Username) { + body = base.Json{ + "mail": d.Username, + "password": d.Password, + "type": 2, + } + } else { + body = base.Json{ + "passport": d.Username, + "password": d.Password, + "type": 1, + } + } + + req := base.RestyClient.R() + + req.SetHeaders(map[string]string{ + /* "origin": "https://www.123pan.com", + "referer": "https://www.123pan.com/",*/ + "user-agent": d.params.UserAgent, + "platform": d.params.Platform, + "app-version": d.params.AppVersion, + "osversion": d.params.OsVersion, + "devicetype": d.params.DeviceType, + "devicename": d.params.DeviceName, + "loginuuid": d.params.LoginUuid, + }) + + if d.params.XChannel != "" && d.params.XAppVersion != "" { + req.SetHeaders(map[string]string{ + "x-channel": d.params.XChannel, + "x-app-version": d.params.XAppVersion, + }) + } + + req.SetQueryParam("auth-key", generateAuthKey()) + + res, err := req.SetBody(body).Post(SignIn) + //res, err := base.RestyClient.R(). + // SetHeaders(map[string]string{ + // /* "origin": "https://www.123pan.com", + // "referer": "https://www.123pan.com/",*/ + // "user-agent": d.params.UserAgent, + // "platform": d.params.Platform, + // "app-version": d.params.AppVersion, + // "osversion": d.params.OsVersion, + // "devicetype": d.params.DeviceType, + // "devicename": d.params.DeviceName, + // //"user-agent": base.UserAgent, + // }). + // SetBody(body).Post(SignIn) + if err != nil { + return err + } + if utils.Json.Get(res.Body(), "code").ToInt() != 200 { + err = fmt.Errorf(utils.Json.Get(res.Body(), "message").ToString()) + } else { + d.AccessToken = utils.Json.Get(res.Body(), "data", "token").ToString() + } + return err +} + +//func authKey(reqUrl string) (*string, error) { +// reqURL, err := url.Parse(reqUrl) +// if err != nil { +// return nil, err +// } +// +// nowUnix := time.Now().Unix() +// random := rand.Intn(0x989680) +// +// p4 := fmt.Sprintf("%d|%d|%s|%s|%s|%s", nowUnix, random, reqURL.Path, "web", "3", AuthKeySalt) +// authKey := fmt.Sprintf("%d-%d-%x", nowUnix, random, md5.Sum([]byte(p4))) +// return &authKey, nil +//} + +func (d *Pan123Share) loginByQrCode() error { + if d.Addition.UniID == "" { + uniID, err := d.generateQrCode() + if uniID == "" && err != nil { + return err + } else { + // 保存 uniID 用于 二维码登录 + d.Addition.UniID = uniID + op.MustSaveDriverStorage(d) + return err + } + } else { + token, err := d.getTokenByUniID() + if token == "" && err != nil { + return err + } else { + d.Addition.AccessToken = token + op.MustSaveDriverStorage(d) + return err + } + } +} + +func (d *Pan123Share) generateQrCode() (string, error) { + var resp QrCodeGenerateResp + _, err := d.request(QrcodeGenerate, http.MethodGet, nil, &resp) + if err != nil { + return "", err + } + // 拼接二维码链接 + qrUrl := fmt.Sprintf(resp.Data.Url+"?uniID=%s", resp.Data.UniID+"&source=123pan&type=login") + // 生成二维码 + qrBytes, _ := qrcode.Encode(qrUrl, qrcode.Medium, 256) + base64Bytes := base64.StdEncoding.EncodeToString(qrBytes) + // 展示二维码 + qrTemplate := ` + + + Or Click Here + ` + qrPage := fmt.Sprintf(qrTemplate, base64Bytes, qrUrl) + return resp.Data.UniID, fmt.Errorf("need verify: \n%s", qrPage) +} + +func (d *Pan123Share) getTokenByUniID() (string, error) { + var resp QrCodeResultResp + _, err := d.request(QrcodeResult, http.MethodGet, func(req *resty.Request) { + req.SetQueryParam("uniID", d.Addition.UniID) + }, &resp) + if err != nil { + return "", err + } + + if resp.Data.LoginStatus == 4 { + return "", errors.New("uniID expired") + } else if resp.Data.Token == "" && resp.Data.LoginStatus == 0 { + return "", errors.New("wait for scan qrcode") + } + + return resp.Data.Token, nil + +} + func signPath(path string, os string, version string) (k string, v string) { table := []byte{'a', 'd', 'e', 'f', 'g', 'h', 'l', 'm', 'y', 'i', 'j', 'n', 'o', 'p', 'k', 'q', 'r', 's', 't', 'u', 'b', 'c', 'v', 'w', 's', 'z'} random := fmt.Sprintf("%.f", math.Round(1e7*rand.Float64())) @@ -113,7 +262,20 @@ func (d *Pan123Share) request(url string, method string, callback base.ReqCallba } body := res.Body() code := utils.Json.Get(body, "code").ToInt() - if code != 0 { + if code != 0 && code != 200 { + if code == 401 && d.Addition.UseQrCodeLogin == false { + err := d.login() + if err != nil { + return nil, err + } + return d.request(url, method, callback, resp) + } else if code == 401 && d.Addition.UseQrCodeLogin == true { + err := d.loginByQrCode() + if err != nil { + return nil, err + } + return d.request(url, method, callback, resp) + } return nil, errors.New(jsoniter.Get(body, "message").ToString()) } return body, nil From a1412b3b4583f9ad7a17b9c11eace322d511b210 Mon Sep 17 00:00:00 2001 From: YangXu <2945065490@qq.com> Date: Sat, 23 Nov 2024 22:25:08 +0800 Subject: [PATCH 6/6] fix(123&123share): update version --- drivers/123/driver.go | 8 +++++++- drivers/123/meta.go | 2 +- drivers/123/util.go | 8 ++++---- drivers/123_share/driver.go | 8 +++++++- drivers/123_share/meta.go | 2 +- drivers/123_share/util.go | 8 ++++---- 6 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/123/driver.go b/drivers/123/driver.go index 7bfe14421c4..c88d72e13e0 100644 --- a/drivers/123/driver.go +++ b/drivers/123/driver.go @@ -6,10 +6,12 @@ import ( "encoding/base64" "encoding/hex" "fmt" + "github.com/google/uuid" "golang.org/x/time/rate" "io" "net/http" "net/url" + "strings" "sync" "time" @@ -56,10 +58,14 @@ func (d *Pan123) Init(ctx context.Context) error { d.params.AppVersion = TVAndroidAppVer } + if d.Addition.LoginUuid == "" { + d.Addition.LoginUuid = strings.ReplaceAll(uuid.New().String(), "-", "") + } + d.params.OsVersion = d.OsVersion - d.params.LoginUuid = d.LoginUuid d.params.DeviceName = d.DeviceName d.params.DeviceType = d.DeiveType + d.params.LoginUuid = d.Addition.LoginUuid _, err := d.request(UserInfo, http.MethodGet, nil, nil) return err diff --git a/drivers/123/meta.go b/drivers/123/meta.go index 4694f585776..c6ef8affc68 100644 --- a/drivers/123/meta.go +++ b/drivers/123/meta.go @@ -18,7 +18,7 @@ type Addition struct { DeviceName string `json:"devicename" default:"Xiaomi"` DeiveType string `json:"devicetype" default:"M1810E5A"` OsVersion string `json:"osversion" default:"Android_8.1.0"` - LoginUuid string `json:"loginuuid" default:"66a4c82756134af2a57d323fd7a5e58c"` + LoginUuid string `json:"loginuuid" default:""` } var config = driver.Config{ diff --git a/drivers/123/util.go b/drivers/123/util.go index 13c3c7de0c3..a500df78ff6 100644 --- a/drivers/123/util.go +++ b/drivers/123/util.go @@ -53,11 +53,11 @@ const ( ) const ( - AndroidUserAgentPrefix = "123pan/v2.4.7" // 123pan/v2.4.7(Android_14;XiaoMi) + AndroidUserAgentPrefix = "123pan/v2.4.8" // 123pan/v2.4.8(Android_14;XiaoMi) AndroidPlatformParam = "android" - AndroidAppVer = "69" - AndroidXAppVer = "2.4.7" - AndroidXChannel = "1002" + AndroidAppVer = "70" + AndroidXAppVer = "2.4.8" + AndroidXChannel = "1001" TVUserAgentPrefix = "123pan_android_tv/1.0.0" // 123pan_android_tv/1.0.0(14;samsung SM-X800) TVPlatformParam = "android_tv" TVAndroidAppVer = "100" diff --git a/drivers/123_share/driver.go b/drivers/123_share/driver.go index 7f8b2541fca..03b4999cbae 100644 --- a/drivers/123_share/driver.go +++ b/drivers/123_share/driver.go @@ -4,9 +4,11 @@ import ( "context" "encoding/base64" "fmt" + "github.com/google/uuid" "golang.org/x/time/rate" "net/http" "net/url" + "strings" "sync" "time" @@ -50,10 +52,14 @@ func (d *Pan123Share) Init(ctx context.Context) error { d.params.AppVersion = TVAndroidAppVer } + if d.Addition.LoginUuid == "" { + d.Addition.LoginUuid = strings.ReplaceAll(uuid.New().String(), "-", "") + } + d.params.OsVersion = d.OsVersion - d.params.LoginUuid = d.LoginUuid d.params.DeviceName = d.DeviceName d.params.DeviceType = d.DeiveType + d.params.LoginUuid = d.LoginUuid _, err := d.request(UserInfo, http.MethodGet, nil, nil) return err diff --git a/drivers/123_share/meta.go b/drivers/123_share/meta.go index 7da542395dd..874658edb31 100644 --- a/drivers/123_share/meta.go +++ b/drivers/123_share/meta.go @@ -20,7 +20,7 @@ type Addition struct { DeviceName string `json:"devicename" default:"Xiaomi"` DeiveType string `json:"devicetype" default:"M1810E5A"` OsVersion string `json:"osversion" default:"Android_8.1.0"` - LoginUuid string `json:"loginuuid" default:"66a4c82756134af2a57d323fd7a5e58c"` + LoginUuid string `json:"loginuuid" default:""` } var config = driver.Config{ diff --git a/drivers/123_share/util.go b/drivers/123_share/util.go index 87a6a89d846..aa835f3d159 100644 --- a/drivers/123_share/util.go +++ b/drivers/123_share/util.go @@ -39,11 +39,11 @@ const ( ) const ( - AndroidUserAgentPrefix = "123pan/v2.4.7" // 123pan/v2.4.7(Android_14;XiaoMi) + AndroidUserAgentPrefix = "123pan/v2.4.8" // 123pan/v2.4.8(Android_14;XiaoMi) AndroidPlatformParam = "android" - AndroidAppVer = "69" - AndroidXAppVer = "2.4.7" - AndroidXChannel = "1002" + AndroidAppVer = "70" + AndroidXAppVer = "2.4.8" + AndroidXChannel = "1001" TVUserAgentPrefix = "123pan_android_tv/1.0.0" // 123pan_android_tv/1.0.0(14;samsung SM-X800) TVPlatformParam = "android_tv" TVAndroidAppVer = "100"