Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/drivers/github_releases/driver.go
1987 views
1
package github_releases
2
3
import (
4
"context"
5
"fmt"
6
"net/http"
7
"strings"
8
"sync"
9
10
"github.com/alist-org/alist/v3/internal/driver"
11
"github.com/alist-org/alist/v3/internal/errs"
12
"github.com/alist-org/alist/v3/internal/model"
13
"github.com/alist-org/alist/v3/pkg/utils"
14
)
15
16
type GithubReleases struct {
17
model.Storage
18
Addition
19
20
points []MountPoint
21
}
22
23
func (d *GithubReleases) Config() driver.Config {
24
return config
25
}
26
27
func (d *GithubReleases) GetAddition() driver.Additional {
28
return &d.Addition
29
}
30
31
func (d *GithubReleases) Init(ctx context.Context) error {
32
d.ParseRepos(d.Addition.RepoStructure)
33
return nil
34
}
35
36
func (d *GithubReleases) Drop(ctx context.Context) error {
37
return nil
38
}
39
40
// processPoint 处理单个挂载点的文件列表
41
func (d *GithubReleases) processPoint(point *MountPoint, path string, args model.ListArgs) []File {
42
var pointFiles []File
43
44
if !d.Addition.ShowAllVersion { // latest
45
point.RequestLatestRelease(d.GetRequest, args.Refresh)
46
pointFiles = d.processLatestVersion(point, path)
47
} else { // all version
48
point.RequestReleases(d.GetRequest, args.Refresh)
49
pointFiles = d.processAllVersions(point, path)
50
}
51
52
return pointFiles
53
}
54
55
// processLatestVersion 处理最新版本的逻辑
56
func (d *GithubReleases) processLatestVersion(point *MountPoint, path string) []File {
57
var pointFiles []File
58
59
if point.Point == path { // 与仓库路径相同
60
pointFiles = append(pointFiles, point.GetLatestRelease()...)
61
if d.Addition.ShowReadme {
62
files := point.GetOtherFile(d.GetRequest, false)
63
pointFiles = append(pointFiles, files...)
64
}
65
} else if strings.HasPrefix(point.Point, path) { // 仓库目录的父目录
66
nextDir := GetNextDir(point.Point, path)
67
if nextDir != "" {
68
dirFile := File{
69
Path: path + "/" + nextDir,
70
FileName: nextDir,
71
Size: point.GetLatestSize(),
72
UpdateAt: point.Release.PublishedAt,
73
CreateAt: point.Release.CreatedAt,
74
Type: "dir",
75
Url: "",
76
}
77
pointFiles = append(pointFiles, dirFile)
78
}
79
}
80
81
return pointFiles
82
}
83
84
// processAllVersions 处理所有版本的逻辑
85
func (d *GithubReleases) processAllVersions(point *MountPoint, path string) []File {
86
var pointFiles []File
87
88
if point.Point == path { // 与仓库路径相同
89
pointFiles = append(pointFiles, point.GetAllVersion()...)
90
if d.Addition.ShowReadme {
91
files := point.GetOtherFile(d.GetRequest, false)
92
pointFiles = append(pointFiles, files...)
93
}
94
} else if strings.HasPrefix(point.Point, path) { // 仓库目录的父目录
95
nextDir := GetNextDir(point.Point, path)
96
if nextDir != "" {
97
dirFile := File{
98
FileName: nextDir,
99
Path: path + "/" + nextDir,
100
Size: point.GetAllVersionSize(),
101
UpdateAt: (*point.Releases)[0].PublishedAt,
102
CreateAt: (*point.Releases)[0].CreatedAt,
103
Type: "dir",
104
Url: "",
105
}
106
pointFiles = append(pointFiles, dirFile)
107
}
108
} else if strings.HasPrefix(path, point.Point) { // 仓库目录的子目录
109
tagName := GetNextDir(path, point.Point)
110
if tagName != "" {
111
pointFiles = append(pointFiles, point.GetReleaseByTagName(tagName)...)
112
}
113
}
114
115
return pointFiles
116
}
117
118
// mergeFiles 合并文件列表,处理重复目录
119
func (d *GithubReleases) mergeFiles(files *[]File, newFiles []File) {
120
for _, newFile := range newFiles {
121
if newFile.Type == "dir" {
122
hasSameDir := false
123
for index := range *files {
124
if (*files)[index].GetName() == newFile.GetName() && (*files)[index].Type == "dir" {
125
hasSameDir = true
126
(*files)[index].Size += newFile.Size
127
break
128
}
129
}
130
if !hasSameDir {
131
*files = append(*files, newFile)
132
}
133
} else {
134
*files = append(*files, newFile)
135
}
136
}
137
}
138
139
func (d *GithubReleases) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
140
files := make([]File, 0)
141
path := fmt.Sprintf("/%s", strings.Trim(dir.GetPath(), "/"))
142
143
if d.Addition.ConcurrentRequests && d.Addition.Token != "" { // 并发处理
144
var mu sync.Mutex
145
var wg sync.WaitGroup
146
147
for i := range d.points {
148
wg.Add(1)
149
go func(point *MountPoint) {
150
defer wg.Done()
151
pointFiles := d.processPoint(point, path, args)
152
153
mu.Lock()
154
d.mergeFiles(&files, pointFiles)
155
mu.Unlock()
156
}(&d.points[i])
157
}
158
wg.Wait()
159
} else { // 串行处理
160
for i := range d.points {
161
point := &d.points[i]
162
pointFiles := d.processPoint(point, path, args)
163
d.mergeFiles(&files, pointFiles)
164
}
165
}
166
167
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
168
return src, nil
169
})
170
}
171
172
func (d *GithubReleases) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
173
url := file.GetID()
174
gh_proxy := strings.TrimSpace(d.Addition.GitHubProxy)
175
176
if gh_proxy != "" {
177
url = strings.Replace(url, "https://github.com", gh_proxy, 1)
178
}
179
180
link := model.Link{
181
URL: url,
182
Header: http.Header{},
183
}
184
return &link, nil
185
}
186
187
func (d *GithubReleases) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {
188
// TODO create folder, optional
189
return nil, errs.NotImplement
190
}
191
192
func (d *GithubReleases) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
193
// TODO move obj, optional
194
return nil, errs.NotImplement
195
}
196
197
func (d *GithubReleases) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) {
198
// TODO rename obj, optional
199
return nil, errs.NotImplement
200
}
201
202
func (d *GithubReleases) Copy(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
203
// TODO copy obj, optional
204
return nil, errs.NotImplement
205
}
206
207
func (d *GithubReleases) Remove(ctx context.Context, obj model.Obj) error {
208
// TODO remove obj, optional
209
return errs.NotImplement
210
}
211
212