mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2025-11-25 03:15:19 +08:00
feat(driver_strm): also shown some files with strm (#969)
* feat(driver_strm): Also shown some files with strm Allow user set some file types that need to shown with strm, usually subtitles Most of code was copy and managed from drivers/alias * 优化 * 优化 * 。 * 添加注释 --------- Co-authored-by: j2rong4cn <j2rong@qq.com> Co-authored-by: j2rong4cn <36783515+j2rong4cn@users.noreply.github.com>
This commit is contained in:
@@ -3,13 +3,17 @@ package strm
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
stdpath "path"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/sign"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/server/common"
|
||||
)
|
||||
|
||||
type Strm struct {
|
||||
@@ -18,6 +22,9 @@ type Strm struct {
|
||||
pathMap map[string][]string
|
||||
autoFlatten bool
|
||||
oneKey string
|
||||
|
||||
supportSuffix map[string]struct{}
|
||||
downloadSuffix map[string]struct{}
|
||||
}
|
||||
|
||||
func (d *Strm) Config() driver.Config {
|
||||
@@ -51,12 +58,24 @@ func (d *Strm) Init(ctx context.Context) error {
|
||||
d.autoFlatten = false
|
||||
}
|
||||
|
||||
d.supportSuffix = supportSuffix()
|
||||
if d.FilterFileTypes != "" {
|
||||
types := strings.Split(d.FilterFileTypes, ",")
|
||||
for _, ext := range types {
|
||||
ext = strings.ToLower(strings.TrimSpace(ext))
|
||||
if ext != "" {
|
||||
supportSuffix[ext] = struct{}{}
|
||||
d.supportSuffix[ext] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d.downloadSuffix = downloadSuffix()
|
||||
if d.DownloadFileTypes != "" {
|
||||
downloadTypes := strings.Split(d.DownloadFileTypes, ",")
|
||||
for _, ext := range downloadTypes {
|
||||
ext = strings.ToLower(strings.TrimSpace(ext))
|
||||
if ext != "" {
|
||||
d.downloadSuffix[ext] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,6 +84,8 @@ func (d *Strm) Init(ctx context.Context) error {
|
||||
|
||||
func (d *Strm) Drop(ctx context.Context) error {
|
||||
d.pathMap = nil
|
||||
d.downloadSuffix = nil
|
||||
d.supportSuffix = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -82,10 +103,25 @@ func (d *Strm) Get(ctx context.Context, path string) (model.Obj, error) {
|
||||
return nil, errs.ObjectNotFound
|
||||
}
|
||||
for _, dst := range dsts {
|
||||
obj, err := d.get(ctx, path, dst, sub)
|
||||
if err == nil {
|
||||
return obj, nil
|
||||
reqPath := stdpath.Join(dst, sub)
|
||||
obj, err := fs.Get(ctx, reqPath, &fs.GetArgs{NoLog: true})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// fs.Get 没报错,说明不是strm生成的路径,需要直接返回
|
||||
size := int64(0)
|
||||
if !obj.IsDir() {
|
||||
size = obj.GetSize()
|
||||
path = reqPath //把路径设置为真实的,供Link直接读取
|
||||
}
|
||||
return &model.Object{
|
||||
Path: path,
|
||||
Name: obj.GetName(),
|
||||
Size: size,
|
||||
Modified: obj.ModTime(),
|
||||
IsFolder: obj.IsDir(),
|
||||
HashInfo: obj.GetHash(),
|
||||
}, nil
|
||||
}
|
||||
return nil, errs.ObjectNotFound
|
||||
}
|
||||
@@ -112,34 +148,33 @@ func (d *Strm) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]
|
||||
}
|
||||
|
||||
func (d *Strm) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
link := d.getLink(ctx, file.GetPath())
|
||||
return &model.Link{
|
||||
MFile: strings.NewReader(link),
|
||||
}, nil
|
||||
}
|
||||
if file.GetID() == "strm" {
|
||||
link := d.getLink(ctx, file.GetPath())
|
||||
return &model.Link{
|
||||
MFile: strings.NewReader(link),
|
||||
}, nil
|
||||
}
|
||||
// ftp,s3
|
||||
if common.GetApiUrl(ctx) == "" {
|
||||
args.Redirect = false
|
||||
}
|
||||
reqPath := file.GetPath()
|
||||
link, _, err := d.link(ctx, reqPath, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (d *Strm) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||
return errors.New("strm Driver cannot make dir")
|
||||
}
|
||||
if link == nil {
|
||||
return &model.Link{
|
||||
URL: fmt.Sprintf("%s/p%s?sign=%s",
|
||||
common.GetApiUrl(ctx),
|
||||
utils.EncodePath(reqPath, true),
|
||||
sign.Sign(reqPath)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Strm) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
return errors.New("strm Driver cannot move file")
|
||||
}
|
||||
|
||||
func (d *Strm) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||
return errors.New("strm Driver cannot rename file")
|
||||
}
|
||||
|
||||
func (d *Strm) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
return errors.New("strm Driver cannot copy file")
|
||||
}
|
||||
|
||||
func (d *Strm) Remove(ctx context.Context, obj model.Obj) error {
|
||||
return errors.New("strm Driver cannot remove file")
|
||||
}
|
||||
|
||||
func (d *Strm) Put(ctx context.Context, dstDir model.Obj, s model.FileStreamer, up driver.UpdateProgress) error {
|
||||
return errors.New("strm Driver cannot put file")
|
||||
// 没有修改link的字段,可直接返回
|
||||
return link, nil
|
||||
}
|
||||
|
||||
var _ driver.Driver = (*Strm)(nil)
|
||||
|
||||
@@ -6,11 +6,12 @@ import (
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
Paths string `json:"paths" required:"true" type:"text"`
|
||||
SiteUrl string `json:"siteUrl" type:"text" required:"false" help:"The prefix URL of the strm file"`
|
||||
FilterFileTypes string `json:"filterFileTypes" type:"text" default:"strm" required:"false" help:"Supports suffix name of strm file"`
|
||||
EncodePath bool `json:"encodePath" default:"true" required:"true" help:"encode the path in the strm file"`
|
||||
LocalModel bool `json:"localModel" default:"false" help:"enable local mode"`
|
||||
Paths string `json:"paths" required:"true" type:"text"`
|
||||
SiteUrl string `json:"siteUrl" type:"text" required:"false" help:"The prefix URL of the strm file"`
|
||||
FilterFileTypes string `json:"filterFileTypes" type:"text" default:"strm" required:"false" help:"Supports suffix name of strm file"`
|
||||
DownloadFileTypes string `json:"downloadFileTypes" type:"text" default:"ass" required:"false" help:"Files need to download with strm (usally subtitles)"`
|
||||
EncodePath bool `json:"encodePath" default:"true" required:"true" help:"encode the path in the strm file"`
|
||||
LocalModel bool `json:"localModel" default:"false" help:"enable local mode"`
|
||||
}
|
||||
|
||||
var config = driver.Config{
|
||||
|
||||
@@ -1,22 +1,36 @@
|
||||
package strm
|
||||
|
||||
var supportSuffix = map[string]struct{}{
|
||||
// video
|
||||
"mp4": {},
|
||||
"mkv": {},
|
||||
"flv": {},
|
||||
"avi": {},
|
||||
"wmv": {},
|
||||
"ts": {},
|
||||
"rmvb": {},
|
||||
"webm": {},
|
||||
// audio
|
||||
"mp3": {},
|
||||
"flac": {},
|
||||
"aac": {},
|
||||
"wav": {},
|
||||
"ogg": {},
|
||||
"m4a": {},
|
||||
"wma": {},
|
||||
"alac": {},
|
||||
func supportSuffix() map[string]struct{} {
|
||||
return map[string]struct{}{
|
||||
// video
|
||||
"mp4": {},
|
||||
"mkv": {},
|
||||
"flv": {},
|
||||
"avi": {},
|
||||
"wmv": {},
|
||||
"ts": {},
|
||||
"rmvb": {},
|
||||
"webm": {},
|
||||
// audio
|
||||
"mp3": {},
|
||||
"flac": {},
|
||||
"aac": {},
|
||||
"wav": {},
|
||||
"ogg": {},
|
||||
"m4a": {},
|
||||
"wma": {},
|
||||
"alac": {},
|
||||
}
|
||||
}
|
||||
|
||||
func downloadSuffix() map[string]struct{} {
|
||||
return map[string]struct{}{
|
||||
// strm
|
||||
"strm": {},
|
||||
// subtitles
|
||||
"ass": {},
|
||||
"srt": {},
|
||||
"vtt": {},
|
||||
"sub": {},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/sign"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/server/common"
|
||||
@@ -51,31 +52,6 @@ func (d *Strm) getRootAndPath(path string) (string, string) {
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
|
||||
func (d *Strm) get(ctx context.Context, path string, dst, sub string) (model.Obj, error) {
|
||||
reqPath := stdpath.Join(dst, sub)
|
||||
obj, err := fs.Get(ctx, reqPath, &fs.GetArgs{NoLog: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
size := int64(0)
|
||||
if !obj.IsDir() {
|
||||
if utils.Ext(obj.GetName()) == "strm" {
|
||||
size = obj.GetSize()
|
||||
} else {
|
||||
file := stdpath.Join(reqPath, obj.GetName())
|
||||
size = int64(len(d.getLink(ctx, file)))
|
||||
}
|
||||
}
|
||||
return &model.Object{
|
||||
Path: path,
|
||||
Name: obj.GetName(),
|
||||
Size: size,
|
||||
Modified: obj.ModTime(),
|
||||
IsFolder: obj.IsDir(),
|
||||
HashInfo: obj.GetHash(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Strm) list(ctx context.Context, dst, sub string, args *fs.ListArgs) ([]model.Obj, error) {
|
||||
reqPath := stdpath.Join(dst, sub)
|
||||
objs, err := fs.List(ctx, reqPath, args)
|
||||
@@ -85,45 +61,44 @@ func (d *Strm) list(ctx context.Context, dst, sub string, args *fs.ListArgs) ([]
|
||||
|
||||
var validObjs []model.Obj
|
||||
for _, obj := range objs {
|
||||
id, name, path := "", obj.GetName(), ""
|
||||
size := int64(0)
|
||||
if !obj.IsDir() {
|
||||
ext := strings.ToLower(utils.Ext(obj.GetName()))
|
||||
if _, ok := supportSuffix[ext]; !ok {
|
||||
path = stdpath.Join(reqPath, obj.GetName())
|
||||
ext := strings.ToLower(utils.Ext(name))
|
||||
if _, ok := d.supportSuffix[ext]; ok {
|
||||
id = "strm"
|
||||
name = strings.TrimSuffix(name, ext) + "strm"
|
||||
size = int64(len(d.getLink(ctx, path)))
|
||||
} else if _, ok := d.downloadSuffix[ext]; ok {
|
||||
size = obj.GetSize()
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
validObjs = append(validObjs, obj)
|
||||
}
|
||||
return utils.SliceConvert(validObjs, func(obj model.Obj) (model.Obj, error) {
|
||||
name := obj.GetName()
|
||||
size := int64(0)
|
||||
if !obj.IsDir() {
|
||||
ext := utils.Ext(name)
|
||||
name = strings.TrimSuffix(name, ext) + "strm"
|
||||
if ext == "strm" {
|
||||
size = obj.GetSize()
|
||||
} else {
|
||||
file := stdpath.Join(reqPath, obj.GetName())
|
||||
size = int64(len(d.getLink(ctx, file)))
|
||||
}
|
||||
}
|
||||
objRes := model.Object{
|
||||
ID: id,
|
||||
Path: path,
|
||||
Name: name,
|
||||
Size: size,
|
||||
Modified: obj.ModTime(),
|
||||
IsFolder: obj.IsDir(),
|
||||
Path: stdpath.Join(reqPath, obj.GetName()),
|
||||
}
|
||||
|
||||
thumb, ok := model.GetThumb(obj)
|
||||
if !ok {
|
||||
return &objRes, nil
|
||||
validObjs = append(validObjs, &objRes)
|
||||
continue
|
||||
}
|
||||
return &model.ObjThumb{
|
||||
|
||||
validObjs = append(validObjs, &model.ObjThumb{
|
||||
Object: objRes,
|
||||
Thumbnail: model.Thumbnail{
|
||||
Thumbnail: thumb,
|
||||
},
|
||||
}, nil
|
||||
})
|
||||
})
|
||||
}
|
||||
return validObjs, nil
|
||||
}
|
||||
|
||||
func (d *Strm) getLink(ctx context.Context, path string) string {
|
||||
@@ -149,3 +124,21 @@ func (d *Strm) getLink(ctx context.Context, path string) string {
|
||||
apiUrl,
|
||||
finalPath)
|
||||
}
|
||||
|
||||
func (d *Strm) link(ctx context.Context, reqPath string, args model.LinkArgs) (*model.Link, model.Obj, error) {
|
||||
storage, reqActualPath, err := op.GetStorageAndActualPath(reqPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !args.Redirect {
|
||||
return op.Link(ctx, storage, reqActualPath, args)
|
||||
}
|
||||
obj, err := fs.Get(ctx, reqPath, &fs.GetArgs{NoLog: true})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if common.ShouldProxy(storage, stdpath.Base(reqPath)) {
|
||||
return nil, obj, nil
|
||||
}
|
||||
return op.Link(ctx, storage, reqActualPath, args)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user