mirror of https://github.com/Xhofe/alist
feat(github_releases): concurrently request the GitHub API (#9211)
parent
2bdc5bef9e
commit
5e15a360b7
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
|
@ -36,88 +37,130 @@ func (d *GithubReleases) Drop(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// processPoint 处理单个挂载点的文件列表
|
||||||
|
func (d *GithubReleases) processPoint(point *MountPoint, path string, args model.ListArgs) []File {
|
||||||
|
var pointFiles []File
|
||||||
|
|
||||||
|
if !d.Addition.ShowAllVersion { // latest
|
||||||
|
point.RequestLatestRelease(d.GetRequest, args.Refresh)
|
||||||
|
pointFiles = d.processLatestVersion(point, path)
|
||||||
|
} else { // all version
|
||||||
|
point.RequestReleases(d.GetRequest, args.Refresh)
|
||||||
|
pointFiles = d.processAllVersions(point, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointFiles
|
||||||
|
}
|
||||||
|
|
||||||
|
// processLatestVersion 处理最新版本的逻辑
|
||||||
|
func (d *GithubReleases) processLatestVersion(point *MountPoint, path string) []File {
|
||||||
|
var pointFiles []File
|
||||||
|
|
||||||
|
if point.Point == path { // 与仓库路径相同
|
||||||
|
pointFiles = append(pointFiles, point.GetLatestRelease()...)
|
||||||
|
if d.Addition.ShowReadme {
|
||||||
|
files := point.GetOtherFile(d.GetRequest, false)
|
||||||
|
pointFiles = append(pointFiles, files...)
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(point.Point, path) { // 仓库目录的父目录
|
||||||
|
nextDir := GetNextDir(point.Point, path)
|
||||||
|
if nextDir != "" {
|
||||||
|
dirFile := File{
|
||||||
|
Path: path + "/" + nextDir,
|
||||||
|
FileName: nextDir,
|
||||||
|
Size: point.GetLatestSize(),
|
||||||
|
UpdateAt: point.Release.PublishedAt,
|
||||||
|
CreateAt: point.Release.CreatedAt,
|
||||||
|
Type: "dir",
|
||||||
|
Url: "",
|
||||||
|
}
|
||||||
|
pointFiles = append(pointFiles, dirFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointFiles
|
||||||
|
}
|
||||||
|
|
||||||
|
// processAllVersions 处理所有版本的逻辑
|
||||||
|
func (d *GithubReleases) processAllVersions(point *MountPoint, path string) []File {
|
||||||
|
var pointFiles []File
|
||||||
|
|
||||||
|
if point.Point == path { // 与仓库路径相同
|
||||||
|
pointFiles = append(pointFiles, point.GetAllVersion()...)
|
||||||
|
if d.Addition.ShowReadme {
|
||||||
|
files := point.GetOtherFile(d.GetRequest, false)
|
||||||
|
pointFiles = append(pointFiles, files...)
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(point.Point, path) { // 仓库目录的父目录
|
||||||
|
nextDir := GetNextDir(point.Point, path)
|
||||||
|
if nextDir != "" {
|
||||||
|
dirFile := File{
|
||||||
|
FileName: nextDir,
|
||||||
|
Path: path + "/" + nextDir,
|
||||||
|
Size: point.GetAllVersionSize(),
|
||||||
|
UpdateAt: (*point.Releases)[0].PublishedAt,
|
||||||
|
CreateAt: (*point.Releases)[0].CreatedAt,
|
||||||
|
Type: "dir",
|
||||||
|
Url: "",
|
||||||
|
}
|
||||||
|
pointFiles = append(pointFiles, dirFile)
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(path, point.Point) { // 仓库目录的子目录
|
||||||
|
tagName := GetNextDir(path, point.Point)
|
||||||
|
if tagName != "" {
|
||||||
|
pointFiles = append(pointFiles, point.GetReleaseByTagName(tagName)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointFiles
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergeFiles 合并文件列表,处理重复目录
|
||||||
|
func (d *GithubReleases) mergeFiles(files *[]File, newFiles []File) {
|
||||||
|
for _, newFile := range newFiles {
|
||||||
|
if newFile.Type == "dir" {
|
||||||
|
hasSameDir := false
|
||||||
|
for index := range *files {
|
||||||
|
if (*files)[index].GetName() == newFile.GetName() && (*files)[index].Type == "dir" {
|
||||||
|
hasSameDir = true
|
||||||
|
(*files)[index].Size += newFile.Size
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasSameDir {
|
||||||
|
*files = append(*files, newFile)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*files = append(*files, newFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (d *GithubReleases) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
func (d *GithubReleases) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
files := make([]File, 0)
|
files := make([]File, 0)
|
||||||
path := fmt.Sprintf("/%s", strings.Trim(dir.GetPath(), "/"))
|
path := fmt.Sprintf("/%s", strings.Trim(dir.GetPath(), "/"))
|
||||||
|
|
||||||
for i := range d.points {
|
if d.Addition.ConcurrentRequests && d.Addition.Token != "" { // 并发处理
|
||||||
point := &d.points[i]
|
var mu sync.Mutex
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
if !d.Addition.ShowAllVersion { // latest
|
for i := range d.points {
|
||||||
point.RequestRelease(d.GetRequest, args.Refresh)
|
wg.Add(1)
|
||||||
|
go func(point *MountPoint) {
|
||||||
|
defer wg.Done()
|
||||||
|
pointFiles := d.processPoint(point, path, args)
|
||||||
|
|
||||||
if point.Point == path { // 与仓库路径相同
|
mu.Lock()
|
||||||
files = append(files, point.GetLatestRelease()...)
|
d.mergeFiles(&files, pointFiles)
|
||||||
if d.Addition.ShowReadme {
|
mu.Unlock()
|
||||||
files = append(files, point.GetOtherFile(d.GetRequest, args.Refresh)...)
|
}(&d.points[i])
|
||||||
}
|
}
|
||||||
} else if strings.HasPrefix(point.Point, path) { // 仓库目录的父目录
|
wg.Wait()
|
||||||
nextDir := GetNextDir(point.Point, path)
|
} else { // 串行处理
|
||||||
if nextDir == "" {
|
for i := range d.points {
|
||||||
continue
|
point := &d.points[i]
|
||||||
}
|
pointFiles := d.processPoint(point, path, args)
|
||||||
|
d.mergeFiles(&files, pointFiles)
|
||||||
hasSameDir := false
|
|
||||||
for index := range files {
|
|
||||||
if files[index].GetName() == nextDir {
|
|
||||||
hasSameDir = true
|
|
||||||
files[index].Size += point.GetLatestSize()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !hasSameDir {
|
|
||||||
files = append(files, File{
|
|
||||||
Path: path + "/" + nextDir,
|
|
||||||
FileName: nextDir,
|
|
||||||
Size: point.GetLatestSize(),
|
|
||||||
UpdateAt: point.Release.PublishedAt,
|
|
||||||
CreateAt: point.Release.CreatedAt,
|
|
||||||
Type: "dir",
|
|
||||||
Url: "",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // all version
|
|
||||||
point.RequestReleases(d.GetRequest, args.Refresh)
|
|
||||||
|
|
||||||
if point.Point == path { // 与仓库路径相同
|
|
||||||
files = append(files, point.GetAllVersion()...)
|
|
||||||
if d.Addition.ShowReadme {
|
|
||||||
files = append(files, point.GetOtherFile(d.GetRequest, args.Refresh)...)
|
|
||||||
}
|
|
||||||
} else if strings.HasPrefix(point.Point, path) { // 仓库目录的父目录
|
|
||||||
nextDir := GetNextDir(point.Point, path)
|
|
||||||
if nextDir == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
hasSameDir := false
|
|
||||||
for index := range files {
|
|
||||||
if files[index].GetName() == nextDir {
|
|
||||||
hasSameDir = true
|
|
||||||
files[index].Size += point.GetAllVersionSize()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !hasSameDir {
|
|
||||||
files = append(files, File{
|
|
||||||
FileName: nextDir,
|
|
||||||
Path: path + "/" + nextDir,
|
|
||||||
Size: point.GetAllVersionSize(),
|
|
||||||
UpdateAt: (*point.Releases)[0].PublishedAt,
|
|
||||||
CreateAt: (*point.Releases)[0].CreatedAt,
|
|
||||||
Type: "dir",
|
|
||||||
Url: "",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else if strings.HasPrefix(path, point.Point) { // 仓库目录的子目录
|
|
||||||
tagName := GetNextDir(path, point.Point)
|
|
||||||
if tagName == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
files = append(files, point.GetReleaseByTagName(tagName)...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,12 @@ import (
|
||||||
|
|
||||||
type Addition struct {
|
type Addition struct {
|
||||||
driver.RootID
|
driver.RootID
|
||||||
RepoStructure string `json:"repo_structure" type:"text" required:"true" default:"alistGo/alist" help:"structure:[path:]org/repo"`
|
RepoStructure string `json:"repo_structure" type:"text" required:"true" default:"alistGo/alist" help:"structure:[path:]org/repo"`
|
||||||
ShowReadme bool `json:"show_readme" type:"bool" default:"true" help:"show README、LICENSE file"`
|
ShowReadme bool `json:"show_readme" type:"bool" default:"true" help:"show README、LICENSE file"`
|
||||||
Token string `json:"token" type:"string" required:"false" help:"GitHub token, if you want to access private repositories or increase the rate limit"`
|
Token string `json:"token" type:"string" required:"false" help:"GitHub token, if you want to access private repositories or increase the rate limit"`
|
||||||
ShowAllVersion bool `json:"show_all_version" type:"bool" default:"false" help:"show all versions"`
|
ShowAllVersion bool `json:"show_all_version" type:"bool" default:"false" help:"show all versions"`
|
||||||
GitHubProxy string `json:"gh_proxy" type:"string" default:"" help:"GitHub proxy, e.g. https://ghproxy.net/github.com or https://gh-proxy.com/github.com "`
|
ConcurrentRequests bool `json:"concurrent_requests" type:"bool" default:"false" help:"To concurrently request the GitHub API, you must enter a GitHub token"`
|
||||||
|
GitHubProxy string `json:"gh_proxy" type:"string" default:"" help:"GitHub proxy, e.g. https://ghproxy.net/github.com or https://gh-proxy.com/github.com "`
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = driver.Config{
|
var config = driver.Config{
|
||||||
|
|
|
@ -18,7 +18,7 @@ type MountPoint struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 请求最新版本
|
// 请求最新版本
|
||||||
func (m *MountPoint) RequestRelease(get func(url string) (*resty.Response, error), refresh bool) {
|
func (m *MountPoint) RequestLatestRelease(get func(url string) (*resty.Response, error), refresh bool) {
|
||||||
if m.Repo == "" {
|
if m.Repo == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 发送 GET 请求
|
// 发送 GET 请求
|
||||||
|
@ -23,7 +23,7 @@ func (d *GithubReleases) GetRequest(url string) (*resty.Response, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if res.StatusCode() != 200 {
|
if res.StatusCode() != 200 {
|
||||||
log.Warn("failed to get request: ", res.StatusCode(), res.String())
|
utils.Log.Warnf("failed to get request: %s %d %s", url, res.StatusCode(), res.String())
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue