Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/drivers/mediatrack/driver.go
1986 views
1
package mediatrack
2
3
import (
4
"context"
5
"crypto/md5"
6
"encoding/hex"
7
"fmt"
8
"io"
9
"net/http"
10
"strconv"
11
"time"
12
13
"github.com/alist-org/alist/v3/drivers/base"
14
"github.com/alist-org/alist/v3/internal/driver"
15
"github.com/alist-org/alist/v3/internal/model"
16
"github.com/alist-org/alist/v3/pkg/utils"
17
"github.com/aws/aws-sdk-go/aws"
18
"github.com/aws/aws-sdk-go/aws/credentials"
19
"github.com/aws/aws-sdk-go/aws/session"
20
"github.com/aws/aws-sdk-go/service/s3/s3manager"
21
"github.com/go-resty/resty/v2"
22
"github.com/google/uuid"
23
log "github.com/sirupsen/logrus"
24
)
25
26
type MediaTrack struct {
27
model.Storage
28
Addition
29
}
30
31
func (d *MediaTrack) Config() driver.Config {
32
return config
33
}
34
35
func (d *MediaTrack) GetAddition() driver.Additional {
36
return &d.Addition
37
}
38
39
func (d *MediaTrack) Init(ctx context.Context) error {
40
_, err := d.request("https://kayle.api.mediatrack.cn/users", http.MethodGet, nil, nil)
41
return err
42
}
43
44
func (d *MediaTrack) Drop(ctx context.Context) error {
45
return nil
46
}
47
48
func (d *MediaTrack) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
49
files, err := d.getFiles(dir.GetID())
50
if err != nil {
51
return nil, err
52
}
53
return utils.SliceConvert(files, func(f File) (model.Obj, error) {
54
size, _ := strconv.ParseInt(f.Size, 10, 64)
55
thumb := ""
56
if f.File != nil && f.File.Cover != "" {
57
thumb = "https://nano.mtres.cn/" + f.File.Cover
58
}
59
return &Object{
60
Object: model.Object{
61
ID: f.ID,
62
Name: f.Title,
63
Modified: f.UpdatedAt,
64
IsFolder: f.File == nil,
65
Size: size,
66
},
67
Thumbnail: model.Thumbnail{Thumbnail: thumb},
68
ParentID: dir.GetID(),
69
}, nil
70
})
71
}
72
73
func (d *MediaTrack) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
74
url := fmt.Sprintf("https://kayn.api.mediatrack.cn/v1/download_token/asset?asset_id=%s&source_type=project&password=&source_id=%s",
75
file.GetID(), d.ProjectID)
76
log.Debugf("media track url: %s", url)
77
body, err := d.request(url, http.MethodGet, nil, nil)
78
if err != nil {
79
return nil, err
80
}
81
token := utils.Json.Get(body, "data", "token").ToString()
82
url = "https://kayn.api.mediatrack.cn/v1/download/redirect?token=" + token
83
res, err := base.NoRedirectClient.R().Get(url)
84
if err != nil {
85
return nil, err
86
}
87
log.Debug(res.String())
88
link := model.Link{
89
URL: url,
90
}
91
log.Debugln("res code: ", res.StatusCode())
92
if res.StatusCode() == 302 {
93
link.URL = res.Header().Get("location")
94
expired := time.Duration(60) * time.Second
95
link.Expiration = &expired
96
}
97
return &link, nil
98
}
99
100
func (d *MediaTrack) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
101
url := fmt.Sprintf("https://jayce.api.mediatrack.cn/v3/assets/%s/children", parentDir.GetID())
102
_, err := d.request(url, http.MethodPost, func(req *resty.Request) {
103
req.SetBody(base.Json{
104
"type": 1,
105
"title": dirName,
106
})
107
}, nil)
108
return err
109
}
110
111
func (d *MediaTrack) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
112
data := base.Json{
113
"parent_id": dstDir.GetID(),
114
"ids": []string{srcObj.GetID()},
115
}
116
url := "https://jayce.api.mediatrack.cn/v4/assets/batch/move"
117
_, err := d.request(url, http.MethodPost, func(req *resty.Request) {
118
req.SetBody(data)
119
}, nil)
120
return err
121
}
122
123
func (d *MediaTrack) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
124
url := "https://jayce.api.mediatrack.cn/v3/assets/" + srcObj.GetID()
125
data := base.Json{
126
"title": newName,
127
}
128
_, err := d.request(url, http.MethodPut, func(req *resty.Request) {
129
req.SetBody(data)
130
}, nil)
131
return err
132
}
133
134
func (d *MediaTrack) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
135
data := base.Json{
136
"parent_id": dstDir.GetID(),
137
"ids": []string{srcObj.GetID()},
138
}
139
url := "https://jayce.api.mediatrack.cn/v4/assets/batch/clone"
140
_, err := d.request(url, http.MethodPost, func(req *resty.Request) {
141
req.SetBody(data)
142
}, nil)
143
return err
144
}
145
146
func (d *MediaTrack) Remove(ctx context.Context, obj model.Obj) error {
147
var parentID string
148
if o, ok := obj.(*Object); ok {
149
parentID = o.ParentID
150
} else {
151
return fmt.Errorf("obj is not local Object")
152
}
153
data := base.Json{
154
"origin_id": parentID,
155
"ids": []string{obj.GetID()},
156
}
157
url := "https://jayce.api.mediatrack.cn/v4/assets/batch/delete"
158
_, err := d.request(url, http.MethodDelete, func(req *resty.Request) {
159
req.SetBody(data)
160
}, nil)
161
return err
162
}
163
164
func (d *MediaTrack) Put(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
165
src := "assets/" + uuid.New().String()
166
var resp UploadResp
167
_, err := d.request("https://jayce.api.mediatrack.cn/v3/storage/tokens/asset", http.MethodGet, func(req *resty.Request) {
168
req.SetQueryParam("src", src)
169
}, &resp)
170
if err != nil {
171
return err
172
}
173
credential := resp.Data.Credentials
174
cfg := &aws.Config{
175
Credentials: credentials.NewStaticCredentials(credential.TmpSecretID, credential.TmpSecretKey, credential.Token),
176
Region: &resp.Data.Region,
177
Endpoint: aws.String("cos.accelerate.myqcloud.com"),
178
}
179
s, err := session.NewSession(cfg)
180
if err != nil {
181
return err
182
}
183
tempFile, err := file.CacheFullInTempFile()
184
if err != nil {
185
return err
186
}
187
defer func() {
188
_ = tempFile.Close()
189
}()
190
uploader := s3manager.NewUploader(s)
191
if file.GetSize() > s3manager.MaxUploadParts*s3manager.DefaultUploadPartSize {
192
uploader.PartSize = file.GetSize() / (s3manager.MaxUploadParts - 1)
193
}
194
input := &s3manager.UploadInput{
195
Bucket: &resp.Data.Bucket,
196
Key: &resp.Data.Object,
197
Body: driver.NewLimitedUploadStream(ctx, &driver.ReaderUpdatingProgress{
198
Reader: &driver.SimpleReaderWithSize{
199
Reader: tempFile,
200
Size: file.GetSize(),
201
},
202
UpdateProgress: up,
203
}),
204
}
205
_, err = uploader.UploadWithContext(ctx, input)
206
if err != nil {
207
return err
208
}
209
url := fmt.Sprintf("https://jayce.api.mediatrack.cn/v3/assets/%s/children", dstDir.GetID())
210
_, err = tempFile.Seek(0, io.SeekStart)
211
if err != nil {
212
return err
213
}
214
h := md5.New()
215
_, err = utils.CopyWithBuffer(h, tempFile)
216
if err != nil {
217
return err
218
}
219
hash := hex.EncodeToString(h.Sum(nil))
220
data := base.Json{
221
"category": 0,
222
"description": file.GetName(),
223
"hash": hash,
224
"mime": file.GetMimetype(),
225
"size": file.GetSize(),
226
"src": src,
227
"title": file.GetName(),
228
"type": 0,
229
}
230
_, err = d.request(url, http.MethodPost, func(req *resty.Request) {
231
req.SetBody(data)
232
}, nil)
233
return err
234
}
235
236
var _ driver.Driver = (*MediaTrack)(nil)
237
238