mirror of https://github.com/Xhofe/alist
211 lines
5.5 KiB
Go
211 lines
5.5 KiB
Go
package github_releases
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/alist-org/alist/v3/internal/driver"
|
|
"github.com/alist-org/alist/v3/internal/errs"
|
|
"github.com/alist-org/alist/v3/internal/model"
|
|
"github.com/alist-org/alist/v3/pkg/utils"
|
|
)
|
|
|
|
type GithubReleases struct {
|
|
model.Storage
|
|
Addition
|
|
|
|
points []MountPoint
|
|
}
|
|
|
|
func (d *GithubReleases) Config() driver.Config {
|
|
return config
|
|
}
|
|
|
|
func (d *GithubReleases) GetAddition() driver.Additional {
|
|
return &d.Addition
|
|
}
|
|
|
|
func (d *GithubReleases) Init(ctx context.Context) error {
|
|
d.ParseRepos(d.Addition.RepoStructure)
|
|
return nil
|
|
}
|
|
|
|
func (d *GithubReleases) Drop(ctx context.Context) error {
|
|
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) {
|
|
files := make([]File, 0)
|
|
path := fmt.Sprintf("/%s", strings.Trim(dir.GetPath(), "/"))
|
|
|
|
if d.Addition.ConcurrentRequests && d.Addition.Token != "" { // 并发处理
|
|
var mu sync.Mutex
|
|
var wg sync.WaitGroup
|
|
|
|
for i := range d.points {
|
|
wg.Add(1)
|
|
go func(point *MountPoint) {
|
|
defer wg.Done()
|
|
pointFiles := d.processPoint(point, path, args)
|
|
|
|
mu.Lock()
|
|
d.mergeFiles(&files, pointFiles)
|
|
mu.Unlock()
|
|
}(&d.points[i])
|
|
}
|
|
wg.Wait()
|
|
} else { // 串行处理
|
|
for i := range d.points {
|
|
point := &d.points[i]
|
|
pointFiles := d.processPoint(point, path, args)
|
|
d.mergeFiles(&files, pointFiles)
|
|
}
|
|
}
|
|
|
|
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
|
return src, nil
|
|
})
|
|
}
|
|
|
|
func (d *GithubReleases) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
|
url := file.GetID()
|
|
gh_proxy := strings.TrimSpace(d.Addition.GitHubProxy)
|
|
|
|
if gh_proxy != "" {
|
|
url = strings.Replace(url, "https://github.com", gh_proxy, 1)
|
|
}
|
|
|
|
link := model.Link{
|
|
URL: url,
|
|
Header: http.Header{},
|
|
}
|
|
return &link, nil
|
|
}
|
|
|
|
func (d *GithubReleases) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {
|
|
// TODO create folder, optional
|
|
return nil, errs.NotImplement
|
|
}
|
|
|
|
func (d *GithubReleases) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
|
|
// TODO move obj, optional
|
|
return nil, errs.NotImplement
|
|
}
|
|
|
|
func (d *GithubReleases) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) {
|
|
// TODO rename obj, optional
|
|
return nil, errs.NotImplement
|
|
}
|
|
|
|
func (d *GithubReleases) Copy(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
|
|
// TODO copy obj, optional
|
|
return nil, errs.NotImplement
|
|
}
|
|
|
|
func (d *GithubReleases) Remove(ctx context.Context, obj model.Obj) error {
|
|
// TODO remove obj, optional
|
|
return errs.NotImplement
|
|
}
|