Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/drivers/gofile/driver.go
1986 views
1
package gofile
2
3
import (
4
"context"
5
"fmt"
6
"time"
7
8
"github.com/alist-org/alist/v3/internal/driver"
9
"github.com/alist-org/alist/v3/internal/errs"
10
"github.com/alist-org/alist/v3/internal/model"
11
"github.com/alist-org/alist/v3/internal/op"
12
)
13
14
type Gofile struct {
15
model.Storage
16
Addition
17
18
accountId string
19
}
20
21
func (d *Gofile) Config() driver.Config {
22
return config
23
}
24
25
func (d *Gofile) GetAddition() driver.Additional {
26
return &d.Addition
27
}
28
29
func (d *Gofile) Init(ctx context.Context) error {
30
if d.APIToken == "" {
31
return fmt.Errorf("API token is required")
32
}
33
34
// Get account ID
35
accountId, err := d.getAccountId(ctx)
36
if err != nil {
37
return fmt.Errorf("failed to get account ID: %w", err)
38
}
39
d.accountId = accountId
40
41
// Get account info to set root folder if not specified
42
if d.RootFolderID == "" {
43
accountInfo, err := d.getAccountInfo(ctx, accountId)
44
if err != nil {
45
return fmt.Errorf("failed to get account info: %w", err)
46
}
47
d.RootFolderID = accountInfo.Data.RootFolder
48
}
49
50
// Save driver storage
51
op.MustSaveDriverStorage(d)
52
return nil
53
}
54
55
func (d *Gofile) Drop(ctx context.Context) error {
56
return nil
57
}
58
59
func (d *Gofile) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
60
var folderId string
61
if dir.GetID() == "" {
62
folderId = d.GetRootId()
63
} else {
64
folderId = dir.GetID()
65
}
66
67
endpoint := fmt.Sprintf("/contents/%s", folderId)
68
69
var response ContentsResponse
70
err := d.getJSON(ctx, endpoint, &response)
71
if err != nil {
72
return nil, err
73
}
74
75
var objects []model.Obj
76
77
// Process children or contents
78
contents := response.Data.Children
79
if contents == nil {
80
contents = response.Data.Contents
81
}
82
83
for _, content := range contents {
84
objects = append(objects, d.convertContentToObj(content))
85
}
86
87
return objects, nil
88
}
89
90
func (d *Gofile) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
91
if file.IsDir() {
92
return nil, errs.NotFile
93
}
94
95
// Create a direct link for the file
96
directLink, err := d.createDirectLink(ctx, file.GetID())
97
if err != nil {
98
return nil, fmt.Errorf("failed to create direct link: %w", err)
99
}
100
101
// Configure cache expiration based on user setting
102
link := &model.Link{
103
URL: directLink,
104
}
105
106
// Only set expiration if LinkExpiry > 0 (0 means no caching)
107
if d.LinkExpiry > 0 {
108
expiration := time.Duration(d.LinkExpiry) * 24 * time.Hour
109
link.Expiration = &expiration
110
}
111
112
return link, nil
113
}
114
115
func (d *Gofile) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {
116
var parentId string
117
if parentDir.GetID() == "" {
118
parentId = d.GetRootId()
119
} else {
120
parentId = parentDir.GetID()
121
}
122
123
data := map[string]interface{}{
124
"parentFolderId": parentId,
125
"folderName": dirName,
126
}
127
128
var response CreateFolderResponse
129
err := d.postJSON(ctx, "/contents/createFolder", data, &response)
130
if err != nil {
131
return nil, err
132
}
133
134
return &model.Object{
135
ID: response.Data.ID,
136
Name: response.Data.Name,
137
IsFolder: true,
138
}, nil
139
}
140
141
func (d *Gofile) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
142
var dstId string
143
if dstDir.GetID() == "" {
144
dstId = d.GetRootId()
145
} else {
146
dstId = dstDir.GetID()
147
}
148
149
data := map[string]interface{}{
150
"contentsId": srcObj.GetID(),
151
"folderId": dstId,
152
}
153
154
err := d.putJSON(ctx, "/contents/move", data, nil)
155
if err != nil {
156
return nil, err
157
}
158
159
// Return updated object
160
return &model.Object{
161
ID: srcObj.GetID(),
162
Name: srcObj.GetName(),
163
Size: srcObj.GetSize(),
164
Modified: srcObj.ModTime(),
165
IsFolder: srcObj.IsDir(),
166
}, nil
167
}
168
169
func (d *Gofile) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) {
170
data := map[string]interface{}{
171
"attribute": "name",
172
"attributeValue": newName,
173
}
174
175
var response UpdateResponse
176
err := d.putJSON(ctx, fmt.Sprintf("/contents/%s/update", srcObj.GetID()), data, &response)
177
if err != nil {
178
return nil, err
179
}
180
181
return &model.Object{
182
ID: srcObj.GetID(),
183
Name: newName,
184
Size: srcObj.GetSize(),
185
Modified: srcObj.ModTime(),
186
IsFolder: srcObj.IsDir(),
187
}, nil
188
}
189
190
func (d *Gofile) Copy(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
191
var dstId string
192
if dstDir.GetID() == "" {
193
dstId = d.GetRootId()
194
} else {
195
dstId = dstDir.GetID()
196
}
197
198
data := map[string]interface{}{
199
"contentsId": srcObj.GetID(),
200
"folderId": dstId,
201
}
202
203
var response CopyResponse
204
err := d.postJSON(ctx, "/contents/copy", data, &response)
205
if err != nil {
206
return nil, err
207
}
208
209
// Get the new ID from the response
210
newId := srcObj.GetID()
211
if response.Data.CopiedContents != nil {
212
if id, ok := response.Data.CopiedContents[srcObj.GetID()]; ok {
213
newId = id
214
}
215
}
216
217
return &model.Object{
218
ID: newId,
219
Name: srcObj.GetName(),
220
Size: srcObj.GetSize(),
221
Modified: srcObj.ModTime(),
222
IsFolder: srcObj.IsDir(),
223
}, nil
224
}
225
226
func (d *Gofile) Remove(ctx context.Context, obj model.Obj) error {
227
data := map[string]interface{}{
228
"contentsId": obj.GetID(),
229
}
230
231
return d.deleteJSON(ctx, "/contents", data)
232
}
233
234
func (d *Gofile) Put(ctx context.Context, dstDir model.Obj, fileStreamer model.FileStreamer, up driver.UpdateProgress) (model.Obj, error) {
235
var folderId string
236
if dstDir.GetID() == "" {
237
folderId = d.GetRootId()
238
} else {
239
folderId = dstDir.GetID()
240
}
241
242
response, err := d.uploadFile(ctx, folderId, fileStreamer, up)
243
if err != nil {
244
return nil, err
245
}
246
247
return &model.Object{
248
ID: response.Data.FileId,
249
Name: response.Data.FileName,
250
Size: fileStreamer.GetSize(),
251
IsFolder: false,
252
}, nil
253
}
254
255
func (d *Gofile) GetArchiveMeta(ctx context.Context, obj model.Obj, args model.ArchiveArgs) (model.ArchiveMeta, error) {
256
return nil, errs.NotImplement
257
}
258
259
func (d *Gofile) ListArchive(ctx context.Context, obj model.Obj, args model.ArchiveInnerArgs) ([]model.Obj, error) {
260
return nil, errs.NotImplement
261
}
262
263
func (d *Gofile) Extract(ctx context.Context, obj model.Obj, args model.ArchiveInnerArgs) (*model.Link, error) {
264
return nil, errs.NotImplement
265
}
266
267
func (d *Gofile) ArchiveDecompress(ctx context.Context, srcObj, dstDir model.Obj, args model.ArchiveDecompressArgs) ([]model.Obj, error) {
268
return nil, errs.NotImplement
269
}
270
271
var _ driver.Driver = (*Gofile)(nil)
272
273