feat(media meta): reverse geocoding from mapbox (#2922)

This commit is contained in:
Aaron Liu
2025-09-26 11:27:46 +08:00
parent 668b542c59
commit 5e5dca40c4
24 changed files with 339 additions and 35 deletions

View File

@@ -4,12 +4,14 @@ import (
"context"
"encoding/gob"
"errors"
"io"
"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/request"
"github.com/cloudreve/Cloudreve/v4/pkg/setting"
"github.com/samber/lo"
"io"
)
type (
@@ -17,7 +19,7 @@ type (
// 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)
Extract(ctx context.Context, ext string, source entitysource.EntitySource, opts ...optionFunc) ([]driver.MediaMeta, error)
}
)
@@ -29,7 +31,7 @@ func init() {
gob.Register([]driver.MediaMeta{})
}
func NewExtractorManager(ctx context.Context, settings setting.Provider, l logging.Logger) Extractor {
func NewExtractorManager(ctx context.Context, settings setting.Provider, l logging.Logger, client request.Client) Extractor {
e := &extractorManager{
settings: settings,
extMap: make(map[string][]Extractor),
@@ -52,6 +54,11 @@ func NewExtractorManager(ctx context.Context, settings setting.Provider, l loggi
extractors = append(extractors, ffprobeE)
}
if e.settings.MediaMetaGeocodingEnabled(ctx) {
geocodingE := newGeocodingExtractor(settings, l, client)
extractors = append(extractors, geocodingE)
}
for _, extractor := range extractors {
for _, ext := range extractor.Exts() {
if e.extMap[ext] == nil {
@@ -73,12 +80,12 @@ 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) {
func (e *extractorManager) Extract(ctx context.Context, ext string, source entitysource.EntitySource, opts ...optionFunc) ([]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)
data, err := e.Extract(ctx, ext, source, append(opts, WithExtracted(res))...)
if err != nil {
return nil, err
}
@@ -92,6 +99,29 @@ func (e *extractorManager) Extract(ctx context.Context, ext string, source entit
}
}
type option struct {
extracted []driver.MediaMeta
language string
}
type optionFunc func(*option)
func (f optionFunc) apply(o *option) {
f(o)
}
func WithExtracted(extracted []driver.MediaMeta) optionFunc {
return optionFunc(func(o *option) {
o.extracted = extracted
})
}
func WithLanguage(language string) optionFunc {
return optionFunc(func(o *option) {
o.language = language
})
}
// 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 {