Compare commits

..

1 Commits

24 changed files with 239 additions and 663 deletions

View File

@ -22,17 +22,6 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Create or update ref
id: create-or-update-ref
uses: ovsds/create-or-update-ref-action@v1
with:
ref: tags/beta
sha: ${{ github.sha }}
- name: Delete beta tag
run: git tag -d beta
continue-on-error: true
- name: changelog # or changelogithub@0.12 if ensure the stable result - name: changelog # or changelogithub@0.12 if ensure the stable result
id: changelog id: changelog
run: | run: |
@ -40,6 +29,7 @@ jobs:
npx changelogithub --output CHANGELOG.md npx changelogithub --output CHANGELOG.md
# npx changelogen@latest --output CHANGELOG.md # npx changelogen@latest --output CHANGELOG.md
- name: Upload assets - name: Upload assets
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
@ -56,10 +46,8 @@ jobs:
include: include:
- target: '!(*musl*|*windows-arm64*|*android*)' # xgo - target: '!(*musl*|*windows-arm64*|*android*)' # xgo
hash: "md5" hash: "md5"
- target: 'linux-!(arm*)-musl*' #musl-not-arm - target: 'linux-*-musl*' #musl
hash: "md5-linux-musl" hash: "md5-linux-musl"
- target: 'linux-arm*-musl*' #musl-arm
hash: "md5-linux-musl-arm"
- target: 'windows-arm64' #win-arm64 - target: 'windows-arm64' #win-arm64
hash: "md5-windows-arm64" hash: "md5-windows-arm64"
- target: 'android-*' #android - target: 'android-*' #android
@ -98,21 +86,3 @@ jobs:
files: build/compress/* files: build/compress/*
prerelease: true prerelease: true
tag_name: beta tag_name: beta
desktop:
needs:
- release
name: Beta Release Desktop
runs-on: ubuntu-latest
steps:
- uses: peter-evans/create-or-update-comment@v4
with:
issue-number: 69
body: |
/release-beta
- triggered by @${{ github.actor }}
- commit sha: ${{ github.sha }}
- view files: https://github.com/alist-org/alist/tree/${{ github.sha }}
reactions: 'rocket'
token: ${{ secrets.MY_TOKEN }}
repository: alist-org/desktop-release

View File

@ -15,10 +15,6 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Delete beta tag
run: git tag -d beta
continue-on-error: true
- run: npx changelogithub # or changelogithub@0.12 if ensure the stable result - run: npx changelogithub # or changelogithub@0.12 if ensure the stable result
env: env:
GITHUB_TOKEN: ${{secrets.MY_TOKEN}} GITHUB_TOKEN: ${{secrets.MY_TOKEN}}

View File

@ -117,7 +117,7 @@ https://alist.nn.ci/guide/sponsor.html
- [VidHub](https://apps.apple.com/app/apple-store/id1659622164?pt=118612019&ct=alist&mt=8) - An elegant cloud video player within the Apple ecosystem. Support for iPhone, iPad, Mac, and Apple TV. - [VidHub](https://apps.apple.com/app/apple-store/id1659622164?pt=118612019&ct=alist&mt=8) - An elegant cloud video player within the Apple ecosystem. Support for iPhone, iPad, Mac, and Apple TV.
- [亚洲云](https://www.asiayun.com/aff/QQCOOQKZ) - 高防服务器|服务器租用|福州高防|广东电信|香港服务器|美国服务器|海外服务器 - 国内靠谱的企业级云计算服务提供商 (sponsored Chinese API server) - [亚洲云](https://www.asiayun.com/aff/QQCOOQKZ) - 高防服务器|服务器租用|福州高防|广东电信|香港服务器|美国服务器|海外服务器 - 国内靠谱的企业级云计算服务提供商 (sponsored Chinese API server)
- [找资源](http://zhaoziyuan2.cc/) - 阿里云盘资源搜索引擎 - [找资源](https://zhaoziyuan.pw/) - 阿里云盘资源搜索引擎
## Contributors ## Contributors

View File

@ -115,7 +115,7 @@ AList 是一个开源软件,如果你碰巧喜欢这个项目,并希望我
- [VidHub](https://apps.apple.com/app/apple-store/id1659622164?pt=118612019&ct=alist&mt=8) - 苹果生态下优雅的网盘视频播放器iPhoneiPadMacApple TV全平台支持。 - [VidHub](https://apps.apple.com/app/apple-store/id1659622164?pt=118612019&ct=alist&mt=8) - 苹果生态下优雅的网盘视频播放器iPhoneiPadMacApple TV全平台支持。
- [亚洲云](https://www.asiayun.com/aff/QQCOOQKZ) - 高防服务器|服务器租用|福州高防|广东电信|香港服务器|美国服务器|海外服务器 - 国内靠谱的企业级云计算服务提供商 (国内API服务器赞助) - [亚洲云](https://www.asiayun.com/aff/QQCOOQKZ) - 高防服务器|服务器租用|福州高防|广东电信|香港服务器|美国服务器|海外服务器 - 国内靠谱的企业级云计算服务提供商 (国内API服务器赞助)
- [找资源](http://zhaoziyuan2.cc/) - 阿里云盘资源搜索引擎 - [找资源](https://zhaoziyuan.pw/) - 阿里云盘资源搜索引擎
## 贡献者 ## 贡献者

View File

@ -117,7 +117,7 @@ https://alist.nn.ci/guide/sponsor.html
- [VidHub](https://apps.apple.com/app/apple-store/id1659622164?pt=118612019&ct=alist&mt=8) - An elegant cloud video player within the Apple ecosystem. Support for iPhone, iPad, Mac, and Apple TV. - [VidHub](https://apps.apple.com/app/apple-store/id1659622164?pt=118612019&ct=alist&mt=8) - An elegant cloud video player within the Apple ecosystem. Support for iPhone, iPad, Mac, and Apple TV.
- [亚洲云](https://www.asiayun.com/aff/QQCOOQKZ) - 高防服务器|服务器租用|福州高防|广东电信|香港服务器|美国服务器|海外服务器 - 国内靠谱的企业级云计算服务提供商 (sponsored Chinese API server) - [亚洲云](https://www.asiayun.com/aff/QQCOOQKZ) - 高防服务器|服务器租用|福州高防|广东电信|香港服务器|美国服务器|海外服务器 - 国内靠谱的企业级云计算服务提供商 (sponsored Chinese API server)
- [找资源](http://zhaoziyuan2.cc/) - 阿里云盘资源搜索引擎 - [找资源](https://zhaoziyuan.pw/) - 阿里云盘资源搜索引擎
## コントリビューター ## コントリビューター

View File

@ -137,19 +137,13 @@ func (d *BaiduPhoto) Link(ctx context.Context, file model.Obj, args model.LinkAr
case *File: case *File:
return d.linkFile(ctx, file, args) return d.linkFile(ctx, file, args)
case *AlbumFile: case *AlbumFile:
// 处理共享相册 f, err := d.CopyAlbumFile(ctx, file)
if d.Uk != file.Uk { if err != nil {
// 有概率无法获取到链接 return nil, err
return d.linkAlbum(ctx, file, args)
// 接口被限制只能使用cookie
// f, err := d.CopyAlbumFile(ctx, file)
// if err != nil {
// return nil, err
// }
// return d.linkFile(ctx, f, args)
} }
return d.linkFile(ctx, &file.File, args) return d.linkFile(ctx, f, args)
// 有概率无法获取到链接
//return d.linkAlbum(ctx, file, args)
} }
return nil, errs.NotFile return nil, errs.NotFile
} }

View File

@ -21,8 +21,8 @@ const (
FILE_API_URL_V2 = API_URL + "/file/v2" FILE_API_URL_V2 = API_URL + "/file/v2"
) )
func (d *BaiduPhoto) Request(client *resty.Client, furl string, method string, callback base.ReqCallback, resp interface{}) (*resty.Response, error) { func (d *BaiduPhoto) Request(furl string, method string, callback base.ReqCallback, resp interface{}) (*resty.Response, error) {
req := client.R(). req := base.RestyClient.R().
SetQueryParam("access_token", d.AccessToken) SetQueryParam("access_token", d.AccessToken)
if callback != nil { if callback != nil {
callback(req) callback(req)
@ -88,11 +88,11 @@ func (d *BaiduPhoto) refreshToken() error {
} }
func (d *BaiduPhoto) Get(furl string, callback base.ReqCallback, resp interface{}) (*resty.Response, error) { func (d *BaiduPhoto) Get(furl string, callback base.ReqCallback, resp interface{}) (*resty.Response, error) {
return d.Request(base.RestyClient, furl, http.MethodGet, callback, resp) return d.Request(furl, http.MethodGet, callback, resp)
} }
func (d *BaiduPhoto) Post(furl string, callback base.ReqCallback, resp interface{}) (*resty.Response, error) { func (d *BaiduPhoto) Post(furl string, callback base.ReqCallback, resp interface{}) (*resty.Response, error) {
return d.Request(base.RestyClient, furl, http.MethodPost, callback, resp) return d.Request(furl, http.MethodPost, callback, resp)
} }
// 获取所有文件 // 获取所有文件
@ -338,33 +338,24 @@ func (d *BaiduPhoto) linkAlbum(ctx context.Context, file *AlbumFile, args model.
headers["X-Forwarded-For"] = args.IP headers["X-Forwarded-For"] = args.IP
} }
resp, err := d.Request(base.NoRedirectClient, ALBUM_API_URL+"/download", http.MethodHead, func(r *resty.Request) { res, err := base.NoRedirectClient.R().
r.SetContext(ctx) SetContext(ctx).
r.SetHeaders(headers) SetHeaders(headers).
r.SetQueryParams(map[string]string{ SetQueryParams(map[string]string{
"access_token": d.AccessToken,
"fsid": fmt.Sprint(file.Fsid), "fsid": fmt.Sprint(file.Fsid),
"album_id": file.AlbumID, "album_id": file.AlbumID,
"tid": fmt.Sprint(file.Tid), "tid": fmt.Sprint(file.Tid),
"uk": fmt.Sprint(file.Uk), "uk": fmt.Sprint(file.Uk),
}) }).
}, nil) Head(ALBUM_API_URL + "/download")
if err != nil {
return nil, err
}
if resp.StatusCode() != 302 {
return nil, fmt.Errorf("not found 302 redirect")
}
location := resp.Header().Get("Location")
if err != nil { if err != nil {
return nil, err return nil, err
} }
link := &model.Link{ link := &model.Link{
URL: location, URL: res.Header().Get("location"),
Header: http.Header{ Header: http.Header{
"User-Agent": []string{headers["User-Agent"]}, "User-Agent": []string{headers["User-Agent"]},
"Referer": []string{"https://photo.baidu.com/"}, "Referer": []string{"https://photo.baidu.com/"},
@ -384,36 +375,22 @@ func (d *BaiduPhoto) linkFile(ctx context.Context, file *File, args model.LinkAr
headers["X-Forwarded-For"] = args.IP headers["X-Forwarded-For"] = args.IP
} }
// var downloadUrl struct { var downloadUrl struct {
// Dlink string `json:"dlink"` Dlink string `json:"dlink"`
// } }
// _, err := d.Get(FILE_API_URL_V1+"/download", func(r *resty.Request) { _, err := d.Get(FILE_API_URL_V2+"/download", func(r *resty.Request) {
// r.SetContext(ctx)
// r.SetHeaders(headers)
// r.SetQueryParams(map[string]string{
// "fsid": fmt.Sprint(file.Fsid),
// })
// }, &downloadUrl)
resp, err := d.Request(base.NoRedirectClient, FILE_API_URL_V1+"/download", http.MethodHead, func(r *resty.Request) {
r.SetContext(ctx) r.SetContext(ctx)
r.SetHeaders(headers) r.SetHeaders(headers)
r.SetQueryParams(map[string]string{ r.SetQueryParams(map[string]string{
"fsid": fmt.Sprint(file.Fsid), "fsid": fmt.Sprint(file.Fsid),
}) })
}, nil) }, &downloadUrl)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if resp.StatusCode() != 302 {
return nil, fmt.Errorf("not found 302 redirect")
}
location := resp.Header().Get("Location")
link := &model.Link{ link := &model.Link{
URL: location, URL: downloadUrl.Dlink,
Header: http.Header{ Header: http.Header{
"User-Agent": []string{headers["User-Agent"]}, "User-Agent": []string{headers["User-Agent"]},
"Referer": []string{"https://photo.baidu.com/"}, "Referer": []string{"https://photo.baidu.com/"},

View File

@ -58,10 +58,34 @@ func (d *GooglePhoto) Link(ctx context.Context, file model.Obj, args model.LinkA
URL: f.BaseURL + "=d", URL: f.BaseURL + "=d",
}, nil }, nil
} else if strings.Contains(f.MimeType, "video/") { } else if strings.Contains(f.MimeType, "video/") {
var width, height int
fmt.Sscanf(f.MediaMetadata.Width, "%d", &width)
fmt.Sscanf(f.MediaMetadata.Height, "%d", &height)
switch {
// 1080P
case width == 1920 && height == 1080:
return &model.Link{
URL: f.BaseURL + "=m37",
}, nil
// 720P
case width == 1280 && height == 720:
return &model.Link{
URL: f.BaseURL + "=m22",
}, nil
// 360P
case width == 640 && height == 360:
return &model.Link{
URL: f.BaseURL + "=m18",
}, nil
default:
return &model.Link{ return &model.Link{
URL: f.BaseURL + "=dv", URL: f.BaseURL + "=dv",
}, nil }, nil
} }
}
return &model.Link{}, nil return &model.Link{}, nil
} }

View File

@ -30,10 +30,6 @@ type Local struct {
model.Storage model.Storage
Addition Addition
mkdirPerm int32 mkdirPerm int32
// zero means no limit
thumbConcurrency int
thumbTokenBucket TokenBucket
} }
func (d *Local) Config() driver.Config { func (d *Local) Config() driver.Config {
@ -66,18 +62,6 @@ func (d *Local) Init(ctx context.Context) error {
return err return err
} }
} }
if d.ThumbConcurrency != "" {
v, err := strconv.ParseUint(d.ThumbConcurrency, 10, 32)
if err != nil {
return err
}
d.thumbConcurrency = int(v)
}
if d.thumbConcurrency == 0 {
d.thumbTokenBucket = NewNopTokenBucket()
} else {
d.thumbTokenBucket = NewStaticTokenBucket(d.thumbConcurrency)
}
return nil return nil
} }
@ -142,6 +126,7 @@ func (d *Local) FileInfoToObj(f fs.FileInfo, reqPath string, fullPath string) mo
}, },
} }
return &file return &file
} }
func (d *Local) GetMeta(ctx context.Context, path string) (model.Obj, error) { func (d *Local) GetMeta(ctx context.Context, path string) (model.Obj, error) {
f, err := os.Stat(path) f, err := os.Stat(path)
@ -193,13 +178,7 @@ func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (
fullPath := file.GetPath() fullPath := file.GetPath()
var link model.Link var link model.Link
if args.Type == "thumb" && utils.Ext(file.GetName()) != "svg" { if args.Type == "thumb" && utils.Ext(file.GetName()) != "svg" {
var buf *bytes.Buffer buf, thumbPath, err := d.getThumb(file)
var thumbPath *string
err := d.thumbTokenBucket.Do(ctx, func() error {
var err error
buf, thumbPath, err = d.getThumb(file)
return err
})
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -9,7 +9,6 @@ type Addition struct {
driver.RootPath driver.RootPath
Thumbnail bool `json:"thumbnail" required:"true" help:"enable thumbnail"` Thumbnail bool `json:"thumbnail" required:"true" help:"enable thumbnail"`
ThumbCacheFolder string `json:"thumb_cache_folder"` ThumbCacheFolder string `json:"thumb_cache_folder"`
ThumbConcurrency string `json:"thumb_concurrency" default:"16" required:"false" help:"Number of concurrent thumbnail generation goroutines. This controls how many thumbnails can be generated in parallel."`
ShowHidden bool `json:"show_hidden" default:"true" required:"false" help:"show hidden directories and files"` ShowHidden bool `json:"show_hidden" default:"true" required:"false" help:"show hidden directories and files"`
MkdirPerm string `json:"mkdir_perm" default:"777"` MkdirPerm string `json:"mkdir_perm" default:"777"`
RecycleBinPath string `json:"recycle_bin_path" default:"delete permanently" help:"path to recycle bin, delete permanently if empty or keep 'delete permanently'"` RecycleBinPath string `json:"recycle_bin_path" default:"delete permanently" help:"path to recycle bin, delete permanently if empty or keep 'delete permanently'"`

View File

@ -1,61 +0,0 @@
package local
import "context"
type TokenBucket interface {
Take() <-chan struct{}
Put()
Do(context.Context, func() error) error
}
// StaticTokenBucket is a bucket with a fixed number of tokens,
// where the retrieval and return of tokens are manually controlled.
// In the initial state, the bucket is full.
type StaticTokenBucket struct {
bucket chan struct{}
}
func NewStaticTokenBucket(size int) StaticTokenBucket {
bucket := make(chan struct{}, size)
for range size {
bucket <- struct{}{}
}
return StaticTokenBucket{bucket: bucket}
}
func (b StaticTokenBucket) Take() <-chan struct{} {
return b.bucket
}
func (b StaticTokenBucket) Put() {
b.bucket <- struct{}{}
}
func (b StaticTokenBucket) Do(ctx context.Context, f func() error) error {
select {
case <-ctx.Done():
return ctx.Err()
case <-b.bucket:
defer b.Put()
}
return f()
}
// NopTokenBucket all function calls to this bucket will success immediately
type NopTokenBucket struct {
nop chan struct{}
}
func NewNopTokenBucket() NopTokenBucket {
nop := make(chan struct{})
close(nop)
return NopTokenBucket{nop}
}
func (b NopTokenBucket) Take() <-chan struct{} {
return b.nop
}
func (b NopTokenBucket) Put() {}
func (b NopTokenBucket) Do(_ context.Context, f func() error) error { return f() }

View File

@ -36,12 +36,12 @@ func isSymlinkDir(f fs.FileInfo, path string) bool {
func GetSnapshot(videoPath string, frameNum int) (imgData *bytes.Buffer, err error) { func GetSnapshot(videoPath string, frameNum int) (imgData *bytes.Buffer, err error) {
srcBuf := bytes.NewBuffer(nil) srcBuf := bytes.NewBuffer(nil)
stream := ffmpeg.Input(videoPath). err = ffmpeg.Input(videoPath).Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", frameNum)}).
Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", frameNum)}).
Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}). Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}).
GlobalArgs("-loglevel", "error").Silent(true). WithOutput(srcBuf, os.Stdout).
WithOutput(srcBuf, os.Stdout) Run()
if err = stream.Run(); err != nil {
if err != nil {
return nil, err return nil, err
} }
return srcBuf, nil return srcBuf, nil

View File

@ -14,7 +14,6 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"golang.org/x/oauth2" "golang.org/x/oauth2"
"net/http" "net/http"
"regexp"
"strconv" "strconv"
"strings" "strings"
) )
@ -49,7 +48,6 @@ func (d *PikPak) Init(ctx context.Context) (err error) {
d.Common.CaptchaToken = token d.Common.CaptchaToken = token
op.MustSaveDriverStorage(d) op.MustSaveDriverStorage(d)
}, },
LowLatencyAddr: "",
} }
} }
@ -67,13 +65,6 @@ func (d *PikPak) Init(ctx context.Context) (err error) {
d.PackageName = WebPackageName d.PackageName = WebPackageName
d.Algorithms = WebAlgorithms d.Algorithms = WebAlgorithms
d.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36" d.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
} else if d.Platform == "pc" {
d.ClientID = PCClientID
d.ClientSecret = PCClientSecret
d.ClientVersion = PCClientVersion
d.PackageName = PCPackageName
d.Algorithms = PCAlgorithms
d.UserAgent = "MainWindow Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) PikPak/2.5.6.4831 Chrome/100.0.4896.160 Electron/18.3.15 Safari/537.36"
} }
if d.Addition.CaptchaToken != "" && d.Addition.RefreshToken == "" { if d.Addition.CaptchaToken != "" && d.Addition.RefreshToken == "" {
@ -99,36 +90,43 @@ func (d *PikPak) Init(ctx context.Context) (err error) {
// 如果已经有RefreshToken直接获取AccessToken // 如果已经有RefreshToken直接获取AccessToken
if d.Addition.RefreshToken != "" { if d.Addition.RefreshToken != "" {
if d.RefreshTokenMethod == "oauth2" {
// 使用 oauth2 刷新令牌 // 使用 oauth2 刷新令牌
// 初始化 oauth2Token // 初始化 oauth2Token
d.initializeOAuth2Token(ctx, oauth2Config, d.Addition.RefreshToken) d.oauth2Token = oauth2.ReuseTokenSource(nil, utils.TokenSource(func() (*oauth2.Token, error) {
if err := d.refreshTokenByOAuth2(); err != nil { return oauth2Config.TokenSource(ctx, &oauth2.Token{
return err RefreshToken: d.Addition.RefreshToken,
} }).Token()
} else { }))
if err := d.refreshToken(d.Addition.RefreshToken); err != nil {
return err
}
}
} else { } else {
// 如果没有填写RefreshToken尝试登录 获取 refreshToken // 如果没有填写RefreshToken尝试登录 获取 refreshToken
if err := d.login(); err != nil { if err := d.login(); err != nil {
return err return err
} }
if d.RefreshTokenMethod == "oauth2" { d.oauth2Token = oauth2.ReuseTokenSource(nil, utils.TokenSource(func() (*oauth2.Token, error) {
d.initializeOAuth2Token(ctx, oauth2Config, d.RefreshToken) return oauth2Config.TokenSource(ctx, &oauth2.Token{
RefreshToken: d.RefreshToken,
}).Token()
}))
} }
token, err := d.oauth2Token.Token()
if err != nil {
return err
} }
d.RefreshToken = token.RefreshToken
d.AccessToken = token.AccessToken
// 获取CaptchaToken // 获取CaptchaToken
err = d.RefreshCaptchaTokenAtLogin(GetAction(http.MethodGet, "https://api-drive.mypikpak.com/drive/v1/files"), d.Common.GetUserID()) err = d.RefreshCaptchaTokenAtLogin(GetAction(http.MethodGet, "https://api-drive.mypikpak.com/drive/v1/files"), d.Username)
if err != nil { if err != nil {
return err return err
} }
// 获取用户ID
userID := token.Extra("sub").(string)
if userID != "" {
d.Common.SetUserID(userID)
}
// 更新UserAgent // 更新UserAgent
if d.Platform == "android" { if d.Platform == "android" {
d.Common.UserAgent = BuildCustomUserAgent(utils.GetMD5EncodeStr(d.Username+d.Password), AndroidClientID, AndroidPackageName, AndroidSdkVersion, AndroidClientVersion, AndroidPackageName, d.Common.UserID) d.Common.UserAgent = BuildCustomUserAgent(utils.GetMD5EncodeStr(d.Username+d.Password), AndroidClientID, AndroidPackageName, AndroidSdkVersion, AndroidClientVersion, AndroidPackageName, d.Common.UserID)
@ -137,15 +135,6 @@ func (d *PikPak) Init(ctx context.Context) (err error) {
// 保存 有效的 RefreshToken // 保存 有效的 RefreshToken
d.Addition.RefreshToken = d.RefreshToken d.Addition.RefreshToken = d.RefreshToken
op.MustSaveDriverStorage(d) op.MustSaveDriverStorage(d)
if d.UseLowLatencyAddress && d.Addition.CustomLowLatencyAddress != "" {
d.Common.LowLatencyAddr = d.Addition.CustomLowLatencyAddress
} else if d.UseLowLatencyAddress {
d.Common.LowLatencyAddr = findLowestLatencyAddress(DlAddr)
d.Addition.CustomLowLatencyAddress = d.Common.LowLatencyAddr
op.MustSaveDriverStorage(d)
}
return nil return nil
} }
@ -165,7 +154,6 @@ func (d *PikPak) List(ctx context.Context, dir model.Obj, args model.ListArgs) (
func (d *PikPak) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { func (d *PikPak) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
var resp File var resp File
var url string
queryParams := map[string]string{ queryParams := map[string]string{
"_magic": "2021", "_magic": "2021",
"usage": "FETCH", "usage": "FETCH",
@ -181,22 +169,14 @@ func (d *PikPak) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
url = resp.WebContentLink link := model.Link{
URL: resp.WebContentLink,
}
if !d.DisableMediaLink && len(resp.Medias) > 0 && resp.Medias[0].Link.Url != "" { if !d.DisableMediaLink && len(resp.Medias) > 0 && resp.Medias[0].Link.Url != "" {
log.Debugln("use media link") log.Debugln("use media link")
url = resp.Medias[0].Link.Url link.URL = resp.Medias[0].Link.Url
} }
return &link, nil
if d.UseLowLatencyAddress && d.Common.LowLatencyAddr != "" {
// 替换为加速链接
re := regexp.MustCompile(`https://[^/]+/download/`)
url = re.ReplaceAllString(url, "https://"+d.Common.LowLatencyAddr+"/download/")
}
return &model.Link{
URL: url,
}, nil
} }
func (d *PikPak) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error { func (d *PikPak) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {

View File

@ -9,14 +9,11 @@ type Addition struct {
driver.RootID driver.RootID
Username string `json:"username" required:"true"` Username string `json:"username" required:"true"`
Password string `json:"password" required:"true"` Password string `json:"password" required:"true"`
Platform string `json:"platform" required:"true" type:"select" options:"android,web,pc"` Platform string `json:"platform" required:"true" type:"select" options:"android,web"`
RefreshToken string `json:"refresh_token" required:"true" default:""` RefreshToken string `json:"refresh_token" required:"true" default:""`
RefreshTokenMethod string `json:"refresh_token_method" required:"true" type:"select" options:"oauth2,http"`
CaptchaToken string `json:"captcha_token" default:""` CaptchaToken string `json:"captcha_token" default:""`
DeviceID string `json:"device_id" required:"false" default:""` DeviceID string `json:"device_id" required:"false" default:""`
DisableMediaLink bool `json:"disable_media_link" default:"true"` DisableMediaLink bool `json:"disable_media_link" default:"true"`
UseLowLatencyAddress bool `json:"use_low_latency_address" default:"false"`
CustomLowLatencyAddress string `json:"custom_low_latency_address" default:""`
} }
var config = driver.Config{ var config = driver.Config{

View File

@ -2,7 +2,6 @@ package pikpak
import ( import (
"bytes" "bytes"
"context"
"crypto/md5" "crypto/md5"
"crypto/sha1" "crypto/sha1"
"encoding/hex" "encoding/hex"
@ -14,7 +13,6 @@ import (
"github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/aliyun/aliyun-oss-go-sdk/oss"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/oauth2"
"io" "io"
"net/http" "net/http"
"path/filepath" "path/filepath"
@ -30,14 +28,21 @@ import (
// do others that not defined in Driver interface // do others that not defined in Driver interface
var AndroidAlgorithms = []string{ var AndroidAlgorithms = []string{
"aDhgaSE3MsjROCmpmsWqP1sJdFJ", "Gez0T9ijiI9WCeTsKSg3SMlx",
"+oaVkqdd8MJuKT+uMr2AYKcd9tdWge3XPEPR2hcePUknd", "zQdbalsolyb1R/",
"u/sd2GgT2fTytRcKzGicHodhvIltMntA3xKw2SRv7S48OdnaQIS5mn", "ftOjr52zt51JD68C3s",
"2WZiae2QuqTOxBKaaqCNHCW3olu2UImelkDzBn", "yeOBMH0JkbQdEFNNwQ0RI9T3wU/v",
"/vJ3upic39lgmrkX855Qx", "BRJrQZiTQ65WtMvwO",
"yNc9ruCVMV7pGV7XvFeuLMOcy1", "je8fqxKPdQVJiy1DM6Bc9Nb1",
"4FPq8mT3JQ1jzcVxMVfwFftLQm33M7i", "niV",
"xozoy5e3Ea", "9hFCW2R1",
"sHKHpe2i96",
"p7c5E6AcXQ/IJUuAEC9W6",
"",
"aRv9hjc9P+Pbn+u3krN6",
"BzStcgE8qVdqjEH16l4",
"SqgeZvL5j9zoHP95xWHt",
"zVof5yaJkPe3VFpadPof",
} }
var WebAlgorithms = []string{ var WebAlgorithms = []string{
@ -58,19 +63,6 @@ var WebAlgorithms = []string{
"NhXXU9rg4XXdzo7u5o", "NhXXU9rg4XXdzo7u5o",
} }
var PCAlgorithms = []string{
"KHBJ07an7ROXDoK7Db",
"G6n399rSWkl7WcQmw5rpQInurc1DkLmLJqE",
"JZD1A3M4x+jBFN62hkr7VDhkkZxb9g3rWqRZqFAAb",
"fQnw/AmSlbbI91Ik15gpddGgyU7U",
"/Dv9JdPYSj3sHiWjouR95NTQff",
"yGx2zuTjbWENZqecNI+edrQgqmZKP",
"ljrbSzdHLwbqcRn",
"lSHAsqCkGDGxQqqwrVu",
"TsWXI81fD1",
"vk7hBjawK/rOSrSWajtbMk95nfgf3",
}
const ( const (
OSSUserAgent = "aliyun-sdk-android/2.9.13(Linux/Android 14/M2004j7ac;UKQ1.231108.001)" OSSUserAgent = "aliyun-sdk-android/2.9.13(Linux/Android 14/M2004j7ac;UKQ1.231108.001)"
OssSecurityTokenHeaderName = "X-OSS-Security-Token" OssSecurityTokenHeaderName = "X-OSS-Security-Token"
@ -80,65 +72,17 @@ const (
const ( const (
AndroidClientID = "YNxT9w7GMdWvEOKa" AndroidClientID = "YNxT9w7GMdWvEOKa"
AndroidClientSecret = "dbw2OtmVEeuUvIptb1Coyg" AndroidClientSecret = "dbw2OtmVEeuUvIptb1Coyg"
AndroidClientVersion = "1.48.3" AndroidClientVersion = "1.47.1"
AndroidPackageName = "com.pikcloud.pikpak" AndroidPackageName = "com.pikcloud.pikpak"
AndroidSdkVersion = "2.0.4.204101" AndroidSdkVersion = "2.0.4.204000"
WebClientID = "YUMx5nI8ZU8Ap8pm" WebClientID = "YUMx5nI8ZU8Ap8pm"
WebClientSecret = "dbw2OtmVEeuUvIptb1Coyg" WebClientSecret = "dbw2OtmVEeuUvIptb1Coyg"
WebClientVersion = "2.0.0" WebClientVersion = "2.0.0"
WebPackageName = "mypikpak.com" WebPackageName = "mypikpak.com"
WebSdkVersion = "8.0.3" WebSdkVersion = "8.0.3"
PCClientID = "YvtoWO6GNHiuCl7x"
PCClientSecret = "1NIH5R1IEe2pAxZE3hv3uA"
PCClientVersion = "undefined" // 2.5.6.4831
PCPackageName = "mypikpak.com"
PCSdkVersion = "8.0.3"
) )
var DlAddr = []string{
"dl-a10b-0621.mypikpak.com",
"dl-a10b-0622.mypikpak.com",
"dl-a10b-0623.mypikpak.com",
"dl-a10b-0624.mypikpak.com",
"dl-a10b-0625.mypikpak.com",
"dl-a10b-0858.mypikpak.com",
"dl-a10b-0859.mypikpak.com",
"dl-a10b-0860.mypikpak.com",
"dl-a10b-0861.mypikpak.com",
"dl-a10b-0862.mypikpak.com",
"dl-a10b-0863.mypikpak.com",
"dl-a10b-0864.mypikpak.com",
"dl-a10b-0865.mypikpak.com",
"dl-a10b-0866.mypikpak.com",
"dl-a10b-0867.mypikpak.com",
"dl-a10b-0868.mypikpak.com",
"dl-a10b-0869.mypikpak.com",
"dl-a10b-0870.mypikpak.com",
"dl-a10b-0871.mypikpak.com",
"dl-a10b-0872.mypikpak.com",
"dl-a10b-0873.mypikpak.com",
"dl-a10b-0874.mypikpak.com",
"dl-a10b-0875.mypikpak.com",
"dl-a10b-0876.mypikpak.com",
"dl-a10b-0877.mypikpak.com",
"dl-a10b-0878.mypikpak.com",
"dl-a10b-0879.mypikpak.com",
"dl-a10b-0880.mypikpak.com",
"dl-a10b-0881.mypikpak.com",
"dl-a10b-0882.mypikpak.com",
"dl-a10b-0883.mypikpak.com",
"dl-a10b-0884.mypikpak.com",
"dl-a10b-0885.mypikpak.com",
"dl-a10b-0886.mypikpak.com",
"dl-a10b-0887.mypikpak.com",
}
func (d *PikPak) login() error { func (d *PikPak) login() error {
// 检查用户名和密码是否为空
if d.Addition.Username == "" || d.Addition.Password == "" {
return errors.New("username or password is empty")
}
url := "https://user.mypikpak.com/v1/auth/signin" url := "https://user.mypikpak.com/v1/auth/signin"
// 使用 用户填写的 CaptchaToken —————— (验证后的captcha_token) // 使用 用户填写的 CaptchaToken —————— (验证后的captcha_token)
if d.GetCaptchaToken() == "" { if d.GetCaptchaToken() == "" {
@ -168,68 +112,39 @@ func (d *PikPak) login() error {
return nil return nil
} }
func (d *PikPak) refreshToken(refreshToken string) error { //func (d *PikPak) refreshToken() error {
url := "https://user.mypikpak.com/v1/auth/token" // url := "https://user.mypikpak.com/v1/auth/token"
var e ErrResp // var e ErrResp
res, err := base.RestyClient.SetRetryCount(1).R().SetError(&e). // res, err := base.RestyClient.SetRetryCount(1).R().SetError(&e).
SetHeader("user-agent", "").SetBody(base.Json{ // SetHeader("user-agent", "").SetBody(base.Json{
"client_id": d.ClientID, // "client_id": ClientID,
"client_secret": d.ClientSecret, // "client_secret": ClientSecret,
"grant_type": "refresh_token", // "grant_type": "refresh_token",
"refresh_token": refreshToken, // "refresh_token": d.RefreshToken,
}).SetQueryParam("client_id", d.ClientID).Post(url) // }).SetQueryParam("client_id", ClientID).Post(url)
if err != nil { // if err != nil {
d.Status = err.Error() // d.Status = err.Error()
op.MustSaveDriverStorage(d) // op.MustSaveDriverStorage(d)
return err // return err
} // }
if e.ErrorCode != 0 { // if e.ErrorCode != 0 {
if e.ErrorCode == 4126 { // if e.ErrorCode == 4126 {
// 1. 未填写 username 或 password // // refresh_token invalid, re-login
if d.Addition.Username == "" || d.Addition.Password == "" { // return d.login()
return errors.New("refresh_token invalid, please re-provide refresh_token") // }
} else { // d.Status = e.Error()
// refresh_token invalid, re-login // op.MustSaveDriverStorage(d)
return d.login() // return errors.New(e.Error())
} // }
} // data := res.Body()
d.Status = e.Error() // d.Status = "work"
op.MustSaveDriverStorage(d) // d.RefreshToken = jsoniter.Get(data, "refresh_token").ToString()
return errors.New(e.Error()) // d.AccessToken = jsoniter.Get(data, "access_token").ToString()
} // d.Common.SetUserID(jsoniter.Get(data, "sub").ToString())
data := res.Body() // d.Addition.RefreshToken = d.RefreshToken
d.Status = "work" // op.MustSaveDriverStorage(d)
d.RefreshToken = jsoniter.Get(data, "refresh_token").ToString() // return nil
d.AccessToken = jsoniter.Get(data, "access_token").ToString() //}
d.Common.SetUserID(jsoniter.Get(data, "sub").ToString())
d.Addition.RefreshToken = d.RefreshToken
op.MustSaveDriverStorage(d)
return nil
}
func (d *PikPak) initializeOAuth2Token(ctx context.Context, oauth2Config *oauth2.Config, refreshToken string) {
d.oauth2Token = oauth2.ReuseTokenSource(nil, utils.TokenSource(func() (*oauth2.Token, error) {
return oauth2Config.TokenSource(ctx, &oauth2.Token{
RefreshToken: refreshToken,
}).Token()
}))
}
func (d *PikPak) refreshTokenByOAuth2() error {
token, err := d.oauth2Token.Token()
if err != nil {
return err
}
d.Status = "work"
d.RefreshToken = token.RefreshToken
d.AccessToken = token.AccessToken
// 获取用户ID
userID := token.Extra("sub").(string)
d.Common.SetUserID(userID)
d.Addition.RefreshToken = d.RefreshToken
op.MustSaveDriverStorage(d)
return nil
}
func (d *PikPak) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { func (d *PikPak) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
req := base.RestyClient.R() req := base.RestyClient.R()
@ -239,15 +154,13 @@ func (d *PikPak) request(url string, method string, callback base.ReqCallback, r
"X-Device-ID": d.GetDeviceID(), "X-Device-ID": d.GetDeviceID(),
"X-Captcha-Token": d.GetCaptchaToken(), "X-Captcha-Token": d.GetCaptchaToken(),
}) })
if d.RefreshTokenMethod == "oauth2" && d.oauth2Token != nil { if d.oauth2Token != nil {
// 使用oauth2 获取 access_token // 使用oauth2 获取 access_token
token, err := d.oauth2Token.Token() token, err := d.oauth2Token.Token()
if err != nil { if err != nil {
return nil, err return nil, err
} }
req.SetAuthScheme(token.TokenType).SetAuthToken(token.AccessToken) req.SetAuthScheme(token.TokenType).SetAuthToken(token.AccessToken)
} else if d.AccessToken != "" {
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
} }
if callback != nil { if callback != nil {
@ -268,19 +181,22 @@ func (d *PikPak) request(url string, method string, callback base.ReqCallback, r
return res.Body(), nil return res.Body(), nil
case 4122, 4121, 16: case 4122, 4121, 16:
// access_token 过期 // access_token 过期
if d.RefreshTokenMethod == "oauth2" {
if err1 := d.refreshTokenByOAuth2(); err1 != nil { //if err1 := d.refreshToken(); err1 != nil {
return nil, err1 // return nil, err1
} //}
} else { t, err := d.oauth2Token.Token()
if err1 := d.refreshToken(d.RefreshToken); err1 != nil { if err != nil {
return nil, err1 return nil, err
}
} }
d.AccessToken = t.AccessToken
d.RefreshToken = t.RefreshToken
d.Addition.RefreshToken = t.RefreshToken
op.MustSaveDriverStorage(d)
return d.request(url, method, callback, resp) return d.request(url, method, callback, resp)
case 9: // 验证码token过期 case 9: // 验证码token过期
if err = d.RefreshCaptchaTokenAtLogin(GetAction(method, url), d.GetUserID()); err != nil { if err = d.RefreshCaptchaTokenAtLogin(GetAction(method, url), d.Common.UserID); err != nil {
return nil, err return nil, err
} }
return d.request(url, method, callback, resp) return d.request(url, method, callback, resp)
@ -338,7 +254,6 @@ type Common struct {
UserAgent string UserAgent string
// 验证码token刷新成功回调 // 验证码token刷新成功回调
RefreshCTokenCk func(token string) RefreshCTokenCk func(token string)
LowLatencyAddr string
} }
func generateDeviceSign(deviceID, packageName string) string { func generateDeviceSign(deviceID, packageName string) string {
@ -422,10 +337,6 @@ func (c *Common) GetDeviceID() string {
return c.DeviceID return c.DeviceID
} }
func (c *Common) GetUserID() string {
return c.UserID
}
// RefreshCaptchaTokenAtLogin 刷新验证码token(登录后) // RefreshCaptchaTokenAtLogin 刷新验证码token(登录后)
func (d *PikPak) RefreshCaptchaTokenAtLogin(action, userID string) error { func (d *PikPak) RefreshCaptchaTokenAtLogin(action, userID string) error {
metas := map[string]string{ metas := map[string]string{
@ -729,46 +640,3 @@ func OssOption(params *S3Params) []oss.Option {
} }
return options return options
} }
type AddressLatency struct {
Address string
Latency time.Duration
}
func checkLatency(address string, wg *sync.WaitGroup, ch chan<- AddressLatency) {
defer wg.Done()
start := time.Now()
resp, err := http.Get("https://" + address + "/generate_204")
if err != nil {
ch <- AddressLatency{Address: address, Latency: time.Hour} // Set high latency on error
return
}
defer resp.Body.Close()
latency := time.Since(start)
ch <- AddressLatency{Address: address, Latency: latency}
}
func findLowestLatencyAddress(addresses []string) string {
var wg sync.WaitGroup
ch := make(chan AddressLatency, len(addresses))
for _, address := range addresses {
wg.Add(1)
go checkLatency(address, &wg, ch)
}
wg.Wait()
close(ch)
var lowestLatencyAddress string
lowestLatency := time.Hour
for result := range ch {
if result.Latency < lowestLatency {
lowestLatency = result.Latency
lowestLatencyAddress = result.Address
}
}
return lowestLatencyAddress
}

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/op"
"net/http" "net/http"
"regexp"
"time" "time"
"github.com/alist-org/alist/v3/internal/driver" "github.com/alist-org/alist/v3/internal/driver"
@ -37,7 +36,6 @@ func (d *PikPakShare) Init(ctx context.Context) error {
d.Common.CaptchaToken = token d.Common.CaptchaToken = token
op.MustSaveDriverStorage(d) op.MustSaveDriverStorage(d)
}, },
LowLatencyAddr: "",
} }
} }
@ -62,21 +60,6 @@ func (d *PikPakShare) Init(ctx context.Context) error {
d.PackageName = WebPackageName d.PackageName = WebPackageName
d.Algorithms = WebAlgorithms d.Algorithms = WebAlgorithms
d.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36" d.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
} else if d.Platform == "pc" {
d.ClientID = PCClientID
d.ClientSecret = PCClientSecret
d.ClientVersion = PCClientVersion
d.PackageName = PCPackageName
d.Algorithms = PCAlgorithms
d.UserAgent = "MainWindow Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) PikPak/2.5.6.4831 Chrome/100.0.4896.160 Electron/18.3.15 Safari/537.36"
}
if d.UseLowLatencyAddress && d.Addition.CustomLowLatencyAddress != "" {
d.Common.LowLatencyAddr = d.Addition.CustomLowLatencyAddress
} else if d.UseLowLatencyAddress {
d.Common.LowLatencyAddr = findLowestLatencyAddress(DlAddr)
d.Addition.CustomLowLatencyAddress = d.Common.LowLatencyAddr
op.MustSaveDriverStorage(d)
} }
// 获取CaptchaToken // 获取CaptchaToken
@ -88,7 +71,6 @@ func (d *PikPakShare) Init(ctx context.Context) error {
if d.SharePwd != "" { if d.SharePwd != "" {
return d.getSharePassToken() return d.getSharePassToken()
} }
return nil return nil
} }
@ -130,16 +112,10 @@ func (d *PikPakShare) Link(ctx context.Context, file model.Obj, args model.LinkA
} }
} }
link := model.Link{
if d.UseLowLatencyAddress && d.Common.LowLatencyAddr != "" {
// 替换为加速链接
re := regexp.MustCompile(`https://[^/]+/download/`)
downloadUrl = re.ReplaceAllString(downloadUrl, "https://"+d.Common.LowLatencyAddr+"/download/")
}
return &model.Link{
URL: downloadUrl, URL: downloadUrl,
}, nil }
return &link, nil
} }
var _ driver.Driver = (*PikPakShare)(nil) var _ driver.Driver = (*PikPakShare)(nil)

View File

@ -9,11 +9,9 @@ type Addition struct {
driver.RootID driver.RootID
ShareId string `json:"share_id" required:"true"` ShareId string `json:"share_id" required:"true"`
SharePwd string `json:"share_pwd"` SharePwd string `json:"share_pwd"`
Platform string `json:"platform" required:"true" type:"select" options:"android,web,pc"` Platform string `json:"platform" required:"true" type:"select" options:"android,web"`
DeviceID string `json:"device_id" required:"false" default:""` DeviceID string `json:"device_id" required:"false" default:""`
UseTransCodingAddress bool `json:"use_transcoding_address" required:"true" default:"false"` UseTransCodingAddress bool `json:"use_transcoding_address" required:"true" default:"false"`
UseLowLatencyAddress bool `json:"use_low_latency_address" default:"false"`
CustomLowLatencyAddress string `json:"custom_low_latency_address" default:""`
} }
var config = driver.Config{ var config = driver.Config{

View File

@ -10,7 +10,6 @@ import (
"net/http" "net/http"
"regexp" "regexp"
"strings" "strings"
"sync"
"time" "time"
"github.com/alist-org/alist/v3/drivers/base" "github.com/alist-org/alist/v3/drivers/base"
@ -18,14 +17,21 @@ import (
) )
var AndroidAlgorithms = []string{ var AndroidAlgorithms = []string{
"aDhgaSE3MsjROCmpmsWqP1sJdFJ", "Gez0T9ijiI9WCeTsKSg3SMlx",
"+oaVkqdd8MJuKT+uMr2AYKcd9tdWge3XPEPR2hcePUknd", "zQdbalsolyb1R/",
"u/sd2GgT2fTytRcKzGicHodhvIltMntA3xKw2SRv7S48OdnaQIS5mn", "ftOjr52zt51JD68C3s",
"2WZiae2QuqTOxBKaaqCNHCW3olu2UImelkDzBn", "yeOBMH0JkbQdEFNNwQ0RI9T3wU/v",
"/vJ3upic39lgmrkX855Qx", "BRJrQZiTQ65WtMvwO",
"yNc9ruCVMV7pGV7XvFeuLMOcy1", "je8fqxKPdQVJiy1DM6Bc9Nb1",
"4FPq8mT3JQ1jzcVxMVfwFftLQm33M7i", "niV",
"xozoy5e3Ea", "9hFCW2R1",
"sHKHpe2i96",
"p7c5E6AcXQ/IJUuAEC9W6",
"",
"aRv9hjc9P+Pbn+u3krN6",
"BzStcgE8qVdqjEH16l4",
"SqgeZvL5j9zoHP95xWHt",
"zVof5yaJkPe3VFpadPof",
} }
var WebAlgorithms = []string{ var WebAlgorithms = []string{
@ -46,75 +52,19 @@ var WebAlgorithms = []string{
"NhXXU9rg4XXdzo7u5o", "NhXXU9rg4XXdzo7u5o",
} }
var PCAlgorithms = []string{
"KHBJ07an7ROXDoK7Db",
"G6n399rSWkl7WcQmw5rpQInurc1DkLmLJqE",
"JZD1A3M4x+jBFN62hkr7VDhkkZxb9g3rWqRZqFAAb",
"fQnw/AmSlbbI91Ik15gpddGgyU7U",
"/Dv9JdPYSj3sHiWjouR95NTQff",
"yGx2zuTjbWENZqecNI+edrQgqmZKP",
"ljrbSzdHLwbqcRn",
"lSHAsqCkGDGxQqqwrVu",
"TsWXI81fD1",
"vk7hBjawK/rOSrSWajtbMk95nfgf3",
}
const ( const (
AndroidClientID = "YNxT9w7GMdWvEOKa" AndroidClientID = "YNxT9w7GMdWvEOKa"
AndroidClientSecret = "dbw2OtmVEeuUvIptb1Coyg" AndroidClientSecret = "dbw2OtmVEeuUvIptb1Coyg"
AndroidClientVersion = "1.48.3" AndroidClientVersion = "1.47.1"
AndroidPackageName = "com.pikcloud.pikpak" AndroidPackageName = "com.pikcloud.pikpak"
AndroidSdkVersion = "2.0.4.204101" AndroidSdkVersion = "2.0.4.204000"
WebClientID = "YUMx5nI8ZU8Ap8pm" WebClientID = "YUMx5nI8ZU8Ap8pm"
WebClientSecret = "dbw2OtmVEeuUvIptb1Coyg" WebClientSecret = "dbw2OtmVEeuUvIptb1Coyg"
WebClientVersion = "2.0.0" WebClientVersion = "2.0.0"
WebPackageName = "mypikpak.com" WebPackageName = "mypikpak.com"
WebSdkVersion = "8.0.3" WebSdkVersion = "8.0.3"
PCClientID = "YvtoWO6GNHiuCl7x"
PCClientSecret = "1NIH5R1IEe2pAxZE3hv3uA"
PCClientVersion = "undefined" // 2.5.6.4831
PCPackageName = "mypikpak.com"
PCSdkVersion = "8.0.3"
) )
var DlAddr = []string{
"dl-a10b-0621.mypikpak.com",
"dl-a10b-0622.mypikpak.com",
"dl-a10b-0623.mypikpak.com",
"dl-a10b-0624.mypikpak.com",
"dl-a10b-0625.mypikpak.com",
"dl-a10b-0858.mypikpak.com",
"dl-a10b-0859.mypikpak.com",
"dl-a10b-0860.mypikpak.com",
"dl-a10b-0861.mypikpak.com",
"dl-a10b-0862.mypikpak.com",
"dl-a10b-0863.mypikpak.com",
"dl-a10b-0864.mypikpak.com",
"dl-a10b-0865.mypikpak.com",
"dl-a10b-0866.mypikpak.com",
"dl-a10b-0867.mypikpak.com",
"dl-a10b-0868.mypikpak.com",
"dl-a10b-0869.mypikpak.com",
"dl-a10b-0870.mypikpak.com",
"dl-a10b-0871.mypikpak.com",
"dl-a10b-0872.mypikpak.com",
"dl-a10b-0873.mypikpak.com",
"dl-a10b-0874.mypikpak.com",
"dl-a10b-0875.mypikpak.com",
"dl-a10b-0876.mypikpak.com",
"dl-a10b-0877.mypikpak.com",
"dl-a10b-0878.mypikpak.com",
"dl-a10b-0879.mypikpak.com",
"dl-a10b-0880.mypikpak.com",
"dl-a10b-0881.mypikpak.com",
"dl-a10b-0882.mypikpak.com",
"dl-a10b-0883.mypikpak.com",
"dl-a10b-0884.mypikpak.com",
"dl-a10b-0885.mypikpak.com",
"dl-a10b-0886.mypikpak.com",
"dl-a10b-0887.mypikpak.com",
}
func (d *PikPakShare) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) { func (d *PikPakShare) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
req := base.RestyClient.R() req := base.RestyClient.R()
req.SetHeaders(map[string]string{ req.SetHeaders(map[string]string{
@ -227,7 +177,6 @@ type Common struct {
UserAgent string UserAgent string
// 验证码token刷新成功回调 // 验证码token刷新成功回调
RefreshCTokenCk func(token string) RefreshCTokenCk func(token string)
LowLatencyAddr string
} }
func (c *Common) SetUserAgent(userAgent string) { func (c *Common) SetUserAgent(userAgent string) {
@ -367,46 +316,3 @@ func (d *PikPakShare) refreshCaptchaToken(action string, metas map[string]string
d.Common.SetCaptchaToken(resp.CaptchaToken) d.Common.SetCaptchaToken(resp.CaptchaToken)
return nil return nil
} }
type AddressLatency struct {
Address string
Latency time.Duration
}
func checkLatency(address string, wg *sync.WaitGroup, ch chan<- AddressLatency) {
defer wg.Done()
start := time.Now()
resp, err := http.Get("https://" + address + "/generate_204")
if err != nil {
ch <- AddressLatency{Address: address, Latency: time.Hour} // Set high latency on error
return
}
defer resp.Body.Close()
latency := time.Since(start)
ch <- AddressLatency{Address: address, Latency: latency}
}
func findLowestLatencyAddress(addresses []string) string {
var wg sync.WaitGroup
ch := make(chan AddressLatency, len(addresses))
for _, address := range addresses {
wg.Add(1)
go checkLatency(address, &wg, ch)
}
wg.Wait()
close(ch)
var lowestLatencyAddress string
lowestLatency := time.Hour
for result := range ch {
if result.Latency < lowestLatency {
lowestLatency = result.Latency
lowestLatencyAddress = result.Address
}
}
return lowestLatencyAddress
}

29
go.mod
View File

@ -13,8 +13,8 @@ require (
github.com/aws/aws-sdk-go v1.55.5 github.com/aws/aws-sdk-go v1.55.5
github.com/blevesearch/bleve/v2 v2.4.2 github.com/blevesearch/bleve/v2 v2.4.2
github.com/caarlos0/env/v9 v9.0.0 github.com/caarlos0/env/v9 v9.0.0
github.com/charmbracelet/bubbles v0.20.0 github.com/charmbracelet/bubbles v0.19.0
github.com/charmbracelet/bubbletea v1.1.0 github.com/charmbracelet/bubbletea v0.27.0
github.com/charmbracelet/lipgloss v0.13.0 github.com/charmbracelet/lipgloss v0.13.0
github.com/city404/v6-public-rpc-proto/go v0.0.0-20240817070657-90f8e24b653e github.com/city404/v6-public-rpc-proto/go v0.0.0-20240817070657-90f8e24b653e
github.com/coreos/go-oidc v2.2.1+incompatible github.com/coreos/go-oidc v2.2.1+incompatible
@ -39,10 +39,10 @@ require (
github.com/json-iterator/go v1.1.12 github.com/json-iterator/go v1.1.12
github.com/larksuite/oapi-sdk-go/v3 v3.3.1 github.com/larksuite/oapi-sdk-go/v3 v3.3.1
github.com/maruel/natural v1.1.1 github.com/maruel/natural v1.1.1
github.com/meilisearch/meilisearch-go v0.27.2 github.com/meilisearch/meilisearch-go v0.28.0
github.com/minio/sio v0.4.0 github.com/minio/sio v0.4.0
github.com/natefinch/lumberjack v2.0.0+incompatible github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/ncw/swift/v2 v2.0.3 github.com/ncw/swift/v2 v2.0.2
github.com/orzogc/fake115uploader v0.3.3-0.20230715111618-58f9eb76f831 github.com/orzogc/fake115uploader v0.3.3-0.20230715111618-58f9eb76f831
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.13.6 github.com/pkg/sftp v1.13.6
@ -58,8 +58,8 @@ require (
github.com/xhofe/tache v0.1.2 github.com/xhofe/tache v0.1.2
github.com/xhofe/wopan-sdk-go v0.1.3 github.com/xhofe/wopan-sdk-go v0.1.3
github.com/zzzhr1990/go-common-entity v0.0.0-20221216044934-fd1c571e3a22 github.com/zzzhr1990/go-common-entity v0.0.0-20221216044934-fd1c571e3a22
golang.org/x/crypto v0.27.0 golang.org/x/crypto v0.26.0
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa
golang.org/x/image v0.19.0 golang.org/x/image v0.19.0
golang.org/x/net v0.28.0 golang.org/x/net v0.28.0
golang.org/x/oauth2 v0.22.0 golang.org/x/oauth2 v0.22.0
@ -77,13 +77,16 @@ require (
github.com/blevesearch/go-faiss v1.0.20 // indirect github.com/blevesearch/go-faiss v1.0.20 // indirect
github.com/blevesearch/zapx/v16 v16.1.5 // indirect github.com/blevesearch/zapx/v16 v16.1.5 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/charmbracelet/x/ansi v0.2.3 // indirect github.com/charmbracelet/x/ansi v0.1.4 // indirect
github.com/charmbracelet/x/term v0.2.0 // indirect github.com/charmbracelet/x/input v0.1.0 // indirect
github.com/charmbracelet/x/term v0.1.1 // indirect
github.com/charmbracelet/x/windows v0.1.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect github.com/cloudwego/iasm v0.2.0 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/ipfs/boxo v0.12.0 // indirect github.com/ipfs/boxo v0.12.0 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
) )
require ( require (
@ -217,13 +220,13 @@ require (
go.etcd.io/bbolt v1.3.8 // indirect go.etcd.io/bbolt v1.3.8 // indirect
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect
golang.org/x/sync v0.8.0 // indirect golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect golang.org/x/sys v0.24.0 // indirect
golang.org/x/term v0.24.0 // indirect golang.org/x/term v0.23.0 // indirect
golang.org/x/text v0.18.0 // indirect golang.org/x/text v0.17.0 // indirect
golang.org/x/tools v0.24.0 // indirect golang.org/x/tools v0.24.0 // indirect
google.golang.org/api v0.169.0 // indirect google.golang.org/api v0.169.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/grpc v1.66.0 google.golang.org/grpc v1.65.0
google.golang.org/protobuf v1.34.2 // indirect google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect

46
go.sum
View File

@ -98,18 +98,20 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charmbracelet/bubbles v0.19.0 h1:gKZkKXPP6GlDk6EcfujDK19PCQqRjaJZQ7QRERx1UF0= github.com/charmbracelet/bubbles v0.19.0 h1:gKZkKXPP6GlDk6EcfujDK19PCQqRjaJZQ7QRERx1UF0=
github.com/charmbracelet/bubbles v0.19.0/go.mod h1:WILteEqZ+krG5c3ntGEMeG99nCupcuIk7V0/zOP0tOA= github.com/charmbracelet/bubbles v0.19.0/go.mod h1:WILteEqZ+krG5c3ntGEMeG99nCupcuIk7V0/zOP0tOA=
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= github.com/charmbracelet/bubbletea v0.27.0 h1:Mznj+vvYuYagD9Pn2mY7fuelGvP0HAXtZYGgRBCbHvU=
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU= github.com/charmbracelet/bubbletea v0.27.0/go.mod h1:5MdP9XH6MbQkgGhnlxUqCNmBXf9I74KRQ8HIidRxV1Y=
github.com/charmbracelet/bubbletea v1.1.0 h1:FjAl9eAL3HBCHenhz/ZPjkKdScmaS5SK69JAK2YJK9c=
github.com/charmbracelet/bubbletea v1.1.0/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4=
github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY= github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM=
github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q=
github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= github.com/charmbracelet/x/input v0.1.0 h1:TEsGSfZYQyOtp+STIjyBq6tpRaorH0qpwZUj8DavAhQ=
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0= github.com/charmbracelet/x/input v0.1.0/go.mod h1:ZZwaBxPF7IG8gWWzPUVqHEtWhc1+HXJPNuerJGRGZ28=
github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI=
github.com/charmbracelet/x/term v0.1.1/go.mod h1:wB1fHt5ECsu3mXYusyzcngVWWlu1KKUmmLhfgr/Flxw=
github.com/charmbracelet/x/windows v0.1.0 h1:gTaxdvzDM5oMa/I2ZNF7wN78X/atWemG9Wph7Ika2k4=
github.com/charmbracelet/x/windows v0.1.0/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
github.com/city404/v6-public-rpc-proto/go v0.0.0-20240817070657-90f8e24b653e h1:GLC8iDDcbt1H8+RkNao2nRGjyNTIo81e1rAJT9/uWYA= github.com/city404/v6-public-rpc-proto/go v0.0.0-20240817070657-90f8e24b653e h1:GLC8iDDcbt1H8+RkNao2nRGjyNTIo81e1rAJT9/uWYA=
@ -340,6 +342,8 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/meilisearch/meilisearch-go v0.27.2 h1:3G21dJ5i208shnLPDsIEZ0L0Geg/5oeXABFV7nlK94k= github.com/meilisearch/meilisearch-go v0.27.2 h1:3G21dJ5i208shnLPDsIEZ0L0Geg/5oeXABFV7nlK94k=
github.com/meilisearch/meilisearch-go v0.27.2/go.mod h1:SxuSqDcPBIykjWz1PX+KzsYzArNLSCadQodWs8extS0= github.com/meilisearch/meilisearch-go v0.27.2/go.mod h1:SxuSqDcPBIykjWz1PX+KzsYzArNLSCadQodWs8extS0=
github.com/meilisearch/meilisearch-go v0.28.0 h1:f3XJ66ZM+R8bANAOLqsjvoq/HhQNpVJPYoNt6QgNzME=
github.com/meilisearch/meilisearch-go v0.28.0/go.mod h1:Szcc9CaDiKIfjdgdt49jlmDKpEzjD+x+b6Y6heMdlQ0=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/minio/sio v0.4.0 h1:u4SWVEm5lXSqU42ZWawV0D9I5AZ5YMmo2RXpEQ/kRhc= github.com/minio/sio v0.4.0 h1:u4SWVEm5lXSqU42ZWawV0D9I5AZ5YMmo2RXpEQ/kRhc=
@ -383,8 +387,8 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/ncw/swift/v2 v2.0.3 h1:8R9dmgFIWs+RiVlisCEfiQiik1hjuR0JnOkLxaP9ihg= github.com/ncw/swift/v2 v2.0.2 h1:jx282pcAKFhmoZBSdMcCRFn9VWkoBIRsCpe+yZq7vEk=
github.com/ncw/swift/v2 v2.0.3/go.mod h1:cbAO76/ZwcFrFlHdXPjaqWZ9R7Hdar7HpjRXBfbjigk= github.com/ncw/swift/v2 v2.0.2/go.mod h1:z0A9RVdYPjNjXVo2pDOPxZ4eu3oarO1P91fTItcb+Kg=
github.com/orzogc/fake115uploader v0.3.3-0.20230715111618-58f9eb76f831 h1:K3T3eu4h5aYIOzUtLjN08L4Qt4WGaJONMgcaD0ayBJQ= github.com/orzogc/fake115uploader v0.3.3-0.20230715111618-58f9eb76f831 h1:K3T3eu4h5aYIOzUtLjN08L4Qt4WGaJONMgcaD0ayBJQ=
github.com/orzogc/fake115uploader v0.3.3-0.20230715111618-58f9eb76f831/go.mod h1:lSHD4lC4zlMl+zcoysdJcd5KFzsWwOD8BJbyg1Ws9Ng= github.com/orzogc/fake115uploader v0.3.3-0.20230715111618-58f9eb76f831/go.mod h1:lSHD4lC4zlMl+zcoysdJcd5KFzsWwOD8BJbyg1Ws9Ng=
github.com/panjf2000/ants/v2 v2.4.2/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OIhFxRNFr4A= github.com/panjf2000/ants/v2 v2.4.2/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OIhFxRNFr4A=
@ -510,6 +514,8 @@ github.com/xhofe/tache v0.1.2 h1:pHrXlrWcbTb4G7hVUDW7Rc+YTUnLJvnLBrdktVE1Fqg=
github.com/xhofe/tache v0.1.2/go.mod h1:iKumPFvywf30FRpAHHCt64G0JHLMzT0K+wyGedHsmTQ= github.com/xhofe/tache v0.1.2/go.mod h1:iKumPFvywf30FRpAHHCt64G0JHLMzT0K+wyGedHsmTQ=
github.com/xhofe/wopan-sdk-go v0.1.3 h1:J58X6v+n25ewBZjb05pKOr7AWGohb+Rdll4CThGh6+A= github.com/xhofe/wopan-sdk-go v0.1.3 h1:J58X6v+n25ewBZjb05pKOr7AWGohb+Rdll4CThGh6+A=
github.com/xhofe/wopan-sdk-go v0.1.3/go.mod h1:dcY9yA28fnaoZPnXZiVTFSkcd7GnIPTpTIIlfSI5z5Q= github.com/xhofe/wopan-sdk-go v0.1.3/go.mod h1:dcY9yA28fnaoZPnXZiVTFSkcd7GnIPTpTIIlfSI5z5Q=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
@ -550,10 +556,8 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.19.0 h1:D9FX4QWkLfkeqaC62SonffIIuYdOk/UE2XKUBgRIBIQ= golang.org/x/image v0.19.0 h1:D9FX4QWkLfkeqaC62SonffIIuYdOk/UE2XKUBgRIBIQ=
golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys= golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys=
@ -628,8 +632,6 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -642,8 +644,6 @@ golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -659,8 +659,6 @@ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
@ -685,10 +683,10 @@ google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY=
google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=

View File

@ -102,13 +102,7 @@ func initURL() {
} }
func CleanTempDir() { func CleanTempDir() {
files, err := os.ReadDir(conf.Conf.TempDir) if err := os.RemoveAll(conf.Conf.TempDir); err != nil {
if err != nil {
log.Errorln("failed list temp file: ", err)
}
for _, file := range files {
if err := os.RemoveAll(filepath.Join(conf.Conf.TempDir, file.Name())); err != nil {
log.Errorln("failed delete temp file: ", err) log.Errorln("failed delete temp file: ", err)
} }
} }
}

View File

@ -87,9 +87,9 @@ func ServeHTTP(w http.ResponseWriter, r *http.Request, name string, modTime time
sendSize := size sendSize := size
var sendContent io.ReadCloser var sendContent io.ReadCloser
ranges, err := http_range.ParseRange(rangeReq, size) ranges, err := http_range.ParseRange(rangeReq, size)
switch { switch err {
case err == nil: case nil:
case errors.Is(err, http_range.ErrNoOverlap): case http_range.ErrNoOverlap:
if size == 0 { if size == 0 {
// Some clients add a Range header to all requests to // Some clients add a Range header to all requests to
// limit the size of the response. If the file is empty, // limit the size of the response. If the file is empty,
@ -105,7 +105,7 @@ func ServeHTTP(w http.ResponseWriter, r *http.Request, name string, modTime time
return return
} }
if sumRangesSize(ranges) > size { if sumRangesSize(ranges) > size || size < 0 {
// The total number of bytes in all the ranges is larger than the size of the file // The total number of bytes in all the ranges is larger than the size of the file
// or unknown file size, ignore the range request. // or unknown file size, ignore the range request.
ranges = nil ranges = nil
@ -174,7 +174,6 @@ func ServeHTTP(w http.ResponseWriter, r *http.Request, name string, modTime time
pw.Close() pw.Close()
}() }()
} }
defer sendContent.Close()
w.Header().Set("Accept-Ranges", "bytes") w.Header().Set("Accept-Ranges", "bytes")
if w.Header().Get("Content-Encoding") == "" { if w.Header().Get("Content-Encoding") == "" {
@ -193,6 +192,7 @@ func ServeHTTP(w http.ResponseWriter, r *http.Request, name string, modTime time
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
} }
//defer sendContent.Close()
} }
func ProcessHeader(origin, override http.Header) http.Header { func ProcessHeader(origin, override http.Header) http.Header {
result := http.Header{} result := http.Header{}

View File

@ -267,12 +267,6 @@ func Link(ctx context.Context, storage driver.Driver, path string, args model.Li
} }
return link, nil return link, nil
} }
if storage.Config().OnlyLocal {
link, err := fn()
return link, file, err
}
link, err, _ := linkG.Do(key, fn) link, err, _ := linkG.Do(key, fn)
return link, file, err return link, file, err
} }

View File

@ -2,8 +2,6 @@ package op
import ( import (
"context" "context"
"fmt"
"runtime"
"sort" "sort"
"strings" "strings"
"time" "time"
@ -85,25 +83,11 @@ func LoadStorage(ctx context.Context, storage model.Storage) error {
return err return err
} }
func getCurrentGoroutineStack() string {
buf := make([]byte, 1<<16)
n := runtime.Stack(buf, false)
return string(buf[:n])
}
// initStorage initialize the driver and store to storagesMap // initStorage initialize the driver and store to storagesMap
func initStorage(ctx context.Context, storage model.Storage, storageDriver driver.Driver) (err error) { func initStorage(ctx context.Context, storage model.Storage, storageDriver driver.Driver) (err error) {
storageDriver.SetStorage(storage) storageDriver.SetStorage(storage)
driverStorage := storageDriver.GetStorage() driverStorage := storageDriver.GetStorage()
defer func() {
if err := recover(); err != nil {
errInfo := fmt.Sprintf("[panic] err: %v\nstack: %s\n", err, getCurrentGoroutineStack())
log.Errorf("panic init storage: %s", errInfo)
driverStorage.SetStatus(errInfo)
MustSaveDriverStorage(storageDriver)
storagesMap.Delete(driverStorage.MountPath)
}
}()
// Unmarshal Addition // Unmarshal Addition
err = utils.Json.UnmarshalFromString(driverStorage.Addition, storageDriver.GetAddition()) err = utils.Json.UnmarshalFromString(driverStorage.Addition, storageDriver.GetAddition())
if err == nil { if err == nil {