Skip to content

Commit 1602722

Browse files
authored
Merge pull request #9444 from okatu-loli/feat/support-quark-stream
feat(quark): support 302 with transcoding and stable video preview
2 parents f5128ff + faa596c commit 1602722

File tree

6 files changed

+184
-43
lines changed

6 files changed

+184
-43
lines changed

drivers/quark_uc/driver.go

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import (
77
"hash"
88
"io"
99
"net/http"
10+
"strings"
1011
"time"
1112

1213
"github.com/alist-org/alist/v3/drivers/base"
1314
"github.com/alist-org/alist/v3/internal/driver"
1415
"github.com/alist-org/alist/v3/internal/errs"
1516
"github.com/alist-org/alist/v3/internal/model"
17+
"github.com/alist-org/alist/v3/internal/op"
1618
streamPkg "github.com/alist-org/alist/v3/internal/stream"
1719
"github.com/alist-org/alist/v3/pkg/utils"
1820
"github.com/go-resty/resty/v2"
@@ -36,6 +38,14 @@ func (d *QuarkOrUC) GetAddition() driver.Additional {
3638

3739
func (d *QuarkOrUC) Init(ctx context.Context) error {
3840
_, err := d.request("/config", http.MethodGet, nil, nil)
41+
if err == nil && d.AdditionVersion != 2 {
42+
d.AdditionVersion = 2
43+
if !d.UseTransCodingAddress && len(d.DownProxyUrl) == 0 {
44+
d.WebProxy = true
45+
d.WebdavPolicy = "native_proxy"
46+
}
47+
op.MustSaveDriverStorage(d)
48+
}
3949
return err
4050
}
4151

@@ -44,39 +54,23 @@ func (d *QuarkOrUC) Drop(ctx context.Context) error {
4454
}
4555

4656
func (d *QuarkOrUC) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
47-
files, err := d.GetFiles(dir.GetID())
48-
if err != nil {
49-
return nil, err
50-
}
51-
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
52-
return fileToObj(src), nil
53-
})
57+
return d.GetFiles(dir.GetID())
5458
}
5559

5660
func (d *QuarkOrUC) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
57-
data := base.Json{
58-
"fids": []string{file.GetID()},
59-
}
60-
var resp DownResp
61-
ua := d.conf.ua
62-
_, err := d.request("/file/download", http.MethodPost, func(req *resty.Request) {
63-
req.SetHeader("User-Agent", ua).
64-
SetBody(data)
65-
}, &resp)
66-
if err != nil {
61+
f := file.(*File)
62+
if d.UseTransCodingAddress && d.config.Name == "Quark" && f.Category == 1 && f.Size > 0 {
63+
link, err := d.getTranscodingLink(file)
64+
if err == nil {
65+
return link, nil
66+
}
67+
if strings.Contains(err.Error(), "plf_invalid") {
68+
log.Warnf("quark transcoding link invalid for %s, fallback to download link: %v", file.GetName(), err)
69+
return d.getDownloadLink(file)
70+
}
6771
return nil, err
6872
}
69-
70-
return &model.Link{
71-
URL: resp.Data[0].DownloadUrl,
72-
Header: http.Header{
73-
"Cookie": []string{d.Cookie},
74-
"Referer": []string{d.conf.referer},
75-
"User-Agent": []string{ua},
76-
},
77-
Concurrency: 3,
78-
PartSize: 10 * utils.MB,
79-
}, nil
73+
return d.getDownloadLink(file)
8074
}
8175

8276
func (d *QuarkOrUC) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {

drivers/quark_uc/meta.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ import (
88
type Addition struct {
99
Cookie string `json:"cookie" required:"true"`
1010
driver.RootID
11-
OrderBy string `json:"order_by" type:"select" options:"none,file_type,file_name,updated_at" default:"none"`
12-
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"`
11+
OrderBy string `json:"order_by" type:"select" options:"none,file_type,file_name,updated_at" default:"none"`
12+
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"`
13+
UseTransCodingAddress bool `json:"use_transcoding_address" help:"You can watch the transcoded video and support 302 redirection" required:"true" default:"false"`
14+
OnlyListVideoFile bool `json:"only_list_video_file" default:"false"`
15+
AdditionVersion int
1316
}
1417

1518
type Conf struct {
@@ -24,7 +27,6 @@ func init() {
2427
return &QuarkOrUC{
2528
config: driver.Config{
2629
Name: "Quark",
27-
OnlyLocal: true,
2830
DefaultRoot: "0",
2931
NoOverwriteUpload: true,
3032
},
@@ -40,7 +42,7 @@ func init() {
4042
return &QuarkOrUC{
4143
config: driver.Config{
4244
Name: "UC",
43-
OnlyLocal: true,
45+
OnlyProxy: true,
4446
DefaultRoot: "0",
4547
NoOverwriteUpload: true,
4648
},

drivers/quark_uc/types.go

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"time"
55

66
"github.com/alist-org/alist/v3/internal/model"
7+
"github.com/alist-org/alist/v3/pkg/utils"
78
)
89

910
type Resp struct {
@@ -18,22 +19,22 @@ type File struct {
1819
Fid string `json:"fid"`
1920
FileName string `json:"file_name"`
2021
//PdirFid string `json:"pdir_fid"`
21-
//Category int `json:"category"`
22+
Category int `json:"category"`
2223
//FileType int `json:"file_type"`
2324
Size int64 `json:"size"`
2425
//FormatType string `json:"format_type"`
2526
//Status int `json:"status"`
2627
//Tags string `json:"tags,omitempty"`
27-
//LCreatedAt int64 `json:"l_created_at"`
28+
LCreatedAt int64 `json:"l_created_at"`
2829
LUpdatedAt int64 `json:"l_updated_at"`
2930
//NameSpace int `json:"name_space"`
3031
//IncludeItems int `json:"include_items,omitempty"`
3132
//RiskType int `json:"risk_type"`
3233
//BackupSign int `json:"backup_sign"`
3334
//Duration int `json:"duration"`
3435
//FileSource string `json:"file_source"`
35-
File bool `json:"file"`
36-
//CreatedAt int64 `json:"created_at"`
36+
File bool `json:"file"`
37+
CreatedAt int64 `json:"created_at"`
3738
UpdatedAt int64 `json:"updated_at"`
3839
//PrivateExtra struct {} `json:"_private_extra"`
3940
//ObjCategory string `json:"obj_category,omitempty"`
@@ -50,6 +51,38 @@ func fileToObj(f File) *model.Object {
5051
}
5152
}
5253

54+
func (f *File) GetSize() int64 {
55+
return f.Size
56+
}
57+
58+
func (f *File) GetName() string {
59+
return f.FileName
60+
}
61+
62+
func (f *File) ModTime() time.Time {
63+
return time.UnixMilli(f.UpdatedAt)
64+
}
65+
66+
func (f *File) CreateTime() time.Time {
67+
return time.UnixMilli(f.CreatedAt)
68+
}
69+
70+
func (f *File) IsDir() bool {
71+
return !f.File
72+
}
73+
74+
func (f *File) GetHash() utils.HashInfo {
75+
return utils.HashInfo{}
76+
}
77+
78+
func (f *File) GetID() string {
79+
return f.Fid
80+
}
81+
82+
func (f *File) GetPath() string {
83+
return ""
84+
}
85+
5386
type SortResp struct {
5487
Resp
5588
Data struct {
@@ -100,6 +133,39 @@ type DownResp struct {
100133
//} `json:"metadata"`
101134
}
102135

136+
type TranscodingResp struct {
137+
Resp
138+
Data struct {
139+
DefaultResolution string `json:"default_resolution"`
140+
OriginDefaultResolution string `json:"origin_default_resolution"`
141+
VideoList []struct {
142+
Resolution string `json:"resolution"`
143+
VideoInfo struct {
144+
Duration int `json:"duration"`
145+
Size int64 `json:"size"`
146+
Format string `json:"format"`
147+
Width int `json:"width"`
148+
Height int `json:"height"`
149+
Bitrate float64 `json:"bitrate"`
150+
Codec string `json:"codec"`
151+
Fps float64 `json:"fps"`
152+
Rotate int `json:"rotate"`
153+
UpdateTime int64 `json:"update_time"`
154+
URL string `json:"url"`
155+
Resolution string `json:"resolution"`
156+
HlsType string `json:"hls_type"`
157+
Finish bool `json:"finish"`
158+
Resoultion string `json:"resoultion"`
159+
Success bool `json:"success"`
160+
} `json:"video_info,omitempty"`
161+
} `json:"video_list"`
162+
FileName string `json:"file_name"`
163+
NameSpace int `json:"name_space"`
164+
Size int64 `json:"size"`
165+
Thumbnail string `json:"thumbnail"`
166+
} `json:"data"`
167+
}
168+
103169
type UpPreResp struct {
104170
Resp
105171
Data struct {

drivers/quark_uc/util.go

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/base64"
77
"errors"
88
"fmt"
9+
"html"
910
"io"
1011
"net/http"
1112
"strconv"
@@ -50,20 +51,29 @@ func (d *QuarkOrUC) request(pathname string, method string, callback base.ReqCal
5051
d.Cookie = cookie.SetStr(d.Cookie, "__puus", __puus.Value)
5152
op.MustSaveDriverStorage(d)
5253
}
54+
if d.UseTransCodingAddress && d.config.Name == "Quark" {
55+
__pus := cookie.GetCookie(res.Cookies(), "__pus")
56+
if __pus != nil {
57+
d.Cookie = cookie.SetStr(d.Cookie, "__pus", __pus.Value)
58+
op.MustSaveDriverStorage(d)
59+
}
60+
}
5361
if e.Status >= 400 || e.Code != 0 {
5462
return nil, errors.New(e.Message)
5563
}
5664
return res.Body(), nil
5765
}
5866

59-
func (d *QuarkOrUC) GetFiles(parent string) ([]File, error) {
60-
files := make([]File, 0)
67+
func (d *QuarkOrUC) GetFiles(parent string) ([]model.Obj, error) {
68+
files := make([]model.Obj, 0)
6169
page := 1
6270
size := 100
6371
query := map[string]string{
64-
"pdir_fid": parent,
65-
"_size": strconv.Itoa(size),
66-
"_fetch_total": "1",
72+
"pdir_fid": parent,
73+
"_size": strconv.Itoa(size),
74+
"_fetch_total": "1",
75+
"fetch_all_file": "1",
76+
"fetch_risk_file_name": "1",
6777
}
6878
if d.OrderBy != "none" {
6979
query["_sort"] = "file_type:asc," + d.OrderBy + ":" + d.OrderDirection
@@ -77,7 +87,16 @@ func (d *QuarkOrUC) GetFiles(parent string) ([]File, error) {
7787
if err != nil {
7888
return nil, err
7989
}
80-
files = append(files, resp.Data.List...)
90+
for _, file := range resp.Data.List {
91+
file.FileName = html.UnescapeString(file.FileName)
92+
if d.OnlyListVideoFile {
93+
if file.IsDir() || file.Category == 1 {
94+
files = append(files, &file)
95+
}
96+
} else {
97+
files = append(files, &file)
98+
}
99+
}
81100
if page*size >= resp.Metadata.Total {
82101
break
83102
}
@@ -86,6 +105,62 @@ func (d *QuarkOrUC) GetFiles(parent string) ([]File, error) {
86105
return files, nil
87106
}
88107

108+
func (d *QuarkOrUC) getDownloadLink(file model.Obj) (*model.Link, error) {
109+
data := base.Json{
110+
"fids": []string{file.GetID()},
111+
}
112+
var resp DownResp
113+
ua := d.conf.ua
114+
_, err := d.request("/file/download", http.MethodPost, func(req *resty.Request) {
115+
req.SetHeader("User-Agent", ua).
116+
SetBody(data)
117+
}, &resp)
118+
if err != nil {
119+
return nil, err
120+
}
121+
122+
return &model.Link{
123+
URL: resp.Data[0].DownloadUrl,
124+
Header: http.Header{
125+
"Cookie": []string{d.Cookie},
126+
"Referer": []string{d.conf.referer},
127+
"User-Agent": []string{ua},
128+
},
129+
Concurrency: 3,
130+
PartSize: 10 * utils.MB,
131+
}, nil
132+
}
133+
134+
func (d *QuarkOrUC) getTranscodingLink(file model.Obj) (*model.Link, error) {
135+
data := base.Json{
136+
"fid": file.GetID(),
137+
"resolutions": "low,normal,high,super,2k,4k",
138+
"supports": "fmp4_av,m3u8,dolby_vision",
139+
}
140+
var resp TranscodingResp
141+
ua := d.conf.ua
142+
143+
_, err := d.request("/file/v2/play/project", http.MethodPost, func(req *resty.Request) {
144+
req.SetHeader("User-Agent", ua).
145+
SetBody(data)
146+
}, &resp)
147+
if err != nil {
148+
return nil, err
149+
}
150+
151+
for _, info := range resp.Data.VideoList {
152+
if info.VideoInfo.URL != "" {
153+
return &model.Link{
154+
URL: info.VideoInfo.URL,
155+
Concurrency: 3,
156+
PartSize: 10 * utils.MB,
157+
}, nil
158+
}
159+
}
160+
161+
return nil, errors.New("no link found")
162+
}
163+
89164
func (d *QuarkOrUC) upPre(file model.FileStreamer, parentId string) (UpPreResp, error) {
90165
now := time.Now()
91166
data := base.Json{

server/handles/down.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ func canProxy(storage driver.Driver, filename string) bool {
187187
if storage.Config().MustProxy() || storage.GetStorage().WebProxy || storage.GetStorage().WebdavProxy() {
188188
return true
189189
}
190+
if storage.GetStorage().Driver == "Quark" && utils.GetFileType(filename) == conf.VIDEO {
191+
return true
192+
}
190193
if utils.SliceContains(conf.SlicesMap[conf.ProxyTypes], utils.Ext(filename)) {
191194
return true
192195
}

server/handles/fsread.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,8 @@ func FsGet(c *gin.Context) {
377377
common.ErrorResp(c, err, 500)
378378
return
379379
}
380-
if storage.Config().MustProxy() || storage.GetStorage().WebProxy {
380+
forceProxyRawURL := storage.GetStorage().Driver == "Quark" && utils.GetFileType(obj.GetName()) == conf.VIDEO
381+
if storage.Config().MustProxy() || storage.GetStorage().WebProxy || forceProxyRawURL {
381382
query := ""
382383
if isEncrypt(meta, reqPath) || setting.GetBool(conf.SignAll) {
383384
query = "?sign=" + sign.Sign(reqPath)

0 commit comments

Comments
 (0)