mirror of https://github.com/cloudreve/Cloudreve
107 lines
2.5 KiB
Go
107 lines
2.5 KiB
Go
package mediameta
|
|
|
|
import (
|
|
"context"
|
|
"encoding/gob"
|
|
"errors"
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/driver"
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/manager/entitysource"
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/logging"
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/setting"
|
|
"github.com/samber/lo"
|
|
"io"
|
|
)
|
|
|
|
type (
|
|
Extractor interface {
|
|
// Exts returns the supported file extensions.
|
|
Exts() []string
|
|
// Extract extracts the media meta from the given source.
|
|
Extract(ctx context.Context, ext string, source entitysource.EntitySource) ([]driver.MediaMeta, error)
|
|
}
|
|
)
|
|
|
|
var (
|
|
ErrFileTooLarge = errors.New("file too large")
|
|
)
|
|
|
|
func init() {
|
|
gob.Register([]driver.MediaMeta{})
|
|
}
|
|
|
|
func NewExtractorManager(ctx context.Context, settings setting.Provider, l logging.Logger) Extractor {
|
|
e := &extractorManager{
|
|
settings: settings,
|
|
extMap: make(map[string][]Extractor),
|
|
}
|
|
|
|
extractors := []Extractor{}
|
|
|
|
if e.settings.MediaMetaExifEnabled(ctx) {
|
|
exifE := newExifExtractor(settings, l)
|
|
extractors = append(extractors, exifE)
|
|
}
|
|
|
|
if e.settings.MediaMetaMusicEnabled(ctx) {
|
|
musicE := newMusicExtractor(settings, l)
|
|
extractors = append(extractors, musicE)
|
|
}
|
|
|
|
if e.settings.MediaMetaFFProbeEnabled(ctx) {
|
|
ffprobeE := newFFProbeExtractor(settings, l)
|
|
extractors = append(extractors, ffprobeE)
|
|
}
|
|
|
|
for _, extractor := range extractors {
|
|
for _, ext := range extractor.Exts() {
|
|
if e.extMap[ext] == nil {
|
|
e.extMap[ext] = []Extractor{}
|
|
}
|
|
e.extMap[ext] = append(e.extMap[ext], extractor)
|
|
}
|
|
}
|
|
|
|
return e
|
|
}
|
|
|
|
type extractorManager struct {
|
|
settings setting.Provider
|
|
extMap map[string][]Extractor
|
|
}
|
|
|
|
func (e *extractorManager) Exts() []string {
|
|
return lo.Keys(e.extMap)
|
|
}
|
|
|
|
func (e *extractorManager) Extract(ctx context.Context, ext string, source entitysource.EntitySource) ([]driver.MediaMeta, error) {
|
|
if extractor, ok := e.extMap[ext]; ok {
|
|
res := []driver.MediaMeta{}
|
|
for _, e := range extractor {
|
|
_, _ = source.Seek(0, io.SeekStart)
|
|
data, err := e.Extract(ctx, ext, source)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
res = append(res, data...)
|
|
}
|
|
|
|
return res, nil
|
|
} else {
|
|
return nil, nil
|
|
}
|
|
}
|
|
|
|
// checkFileSize checks if the file size exceeds the limit.
|
|
func checkFileSize(localLimit, remoteLimit int64, source entitysource.EntitySource) error {
|
|
if source.IsLocal() && localLimit > 0 && source.Entity().Size() > localLimit {
|
|
return ErrFileTooLarge
|
|
}
|
|
|
|
if !source.IsLocal() && remoteLimit > 0 && source.Entity().Size() > remoteLimit {
|
|
return ErrFileTooLarge
|
|
}
|
|
|
|
return nil
|
|
}
|