mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 11:36:36 +08:00
Add ISO media scan support
This commit is contained in:
@@ -43,9 +43,14 @@ var videoExtensions = map[string]struct{}{
|
||||
".3gp": {},
|
||||
".mpg": {},
|
||||
".mpeg": {},
|
||||
".iso": {},
|
||||
".strm": {},
|
||||
}
|
||||
|
||||
func mediaExtensionSupportsProbe(ext string) bool {
|
||||
return ext != ".strm" && ext != ".iso"
|
||||
}
|
||||
|
||||
// ScannerService walks libraries on disk and upserts model.Media rows.
|
||||
type ScannerService struct {
|
||||
cfg *config.Config
|
||||
|
||||
@@ -76,7 +76,7 @@ func (s *ScannerService) ingestCloudFile(ctx context.Context, lib *model.Library
|
||||
isNewMedia = !exists
|
||||
needsTrackProbe = !exists || cloudTrackMetadataMissing(existing)
|
||||
if exists && existing.LibraryID == lib.ID && existing.SizeBytes == size && existing.STRMURL == expectedSTRMURL && !cloudMetadataNeedsRefresh(existing, localMeta) && !cloudDerivedMetadataNeedsRefresh(existing, m) {
|
||||
if needsTrackProbe && ext != ".strm" {
|
||||
if needsTrackProbe && mediaExtensionSupportsProbe(ext) {
|
||||
s.queueCloudMediaProbeWithBudget(typ, ref, path, probeBudget)
|
||||
}
|
||||
res.Skipped++
|
||||
@@ -90,7 +90,7 @@ func (s *ScannerService) ingestCloudFile(ctx context.Context, lib *model.Library
|
||||
}
|
||||
if isNewMedia && writeBatch != nil {
|
||||
var after func()
|
||||
if needsTrackProbe && ext != ".strm" {
|
||||
if needsTrackProbe && mediaExtensionSupportsProbe(ext) {
|
||||
after = func() {
|
||||
s.queueCloudMediaProbeWithBudget(typ, ref, path, probeBudget)
|
||||
}
|
||||
@@ -103,7 +103,7 @@ func (s *ScannerService) ingestCloudFile(ctx context.Context, lib *model.Library
|
||||
s.log.Warn("upsert cloud media failed", zap.String("path", path), zap.Error(err))
|
||||
return
|
||||
}
|
||||
if needsTrackProbe && ext != ".strm" {
|
||||
if needsTrackProbe && mediaExtensionSupportsProbe(ext) {
|
||||
s.queueCloudMediaProbeWithBudget(typ, ref, path, probeBudget)
|
||||
}
|
||||
if isNewMedia {
|
||||
|
||||
@@ -63,6 +63,34 @@ func TestIngestPathAddsSingleFile(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanLibraryImportsISOImage(t *testing.T) {
|
||||
sc, repos := newScannerTestEnv(t)
|
||||
root := t.TempDir()
|
||||
lib := model.Library{Name: "Movies", Path: root, Type: "movie", Enabled: true}
|
||||
if err := repos.Library.Create(t.Context(), &lib); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
isoPath := filepath.Join(root, "Movie.Name.2026.iso")
|
||||
if err := os.WriteFile(isoPath, []byte("iso image"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res, err := sc.ScanLibrary(t.Context(), lib.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("scan: %v", err)
|
||||
}
|
||||
if res.Added != 1 || res.ErrorCount != 0 {
|
||||
t.Fatalf("scan result = %#v, want one ISO image added without errors", res)
|
||||
}
|
||||
var media model.Media
|
||||
if err := repos.DB.First(&media).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if media.Path != isoPath || media.Container != "iso" {
|
||||
t.Fatalf("ISO media = %#v, want path %q and container iso", media, isoPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanLibraryReturnsNotFoundForMissingLibrary(t *testing.T) {
|
||||
sc, _ := newScannerTestEnv(t)
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ func (s *ScannerService) buildLocalScanMedia(in localScanMediaInput) *model.Medi
|
||||
}
|
||||
|
||||
func (s *ScannerService) localProbeAfter(path, ext string) func() {
|
||||
if ext == ".strm" || s.probe == nil {
|
||||
if !mediaExtensionSupportsProbe(ext) || s.probe == nil {
|
||||
return nil
|
||||
}
|
||||
return func() {
|
||||
|
||||
@@ -93,8 +93,8 @@ func TestGenerateSTRMFromTreeSupportsCommonVideoExtensions(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if res.Generated != 5 || len(res.Errors) != 0 {
|
||||
t.Fatalf("result = %#v, want five common video sources generated and iso ignored", res)
|
||||
if res.Generated != 6 || len(res.Errors) != 0 {
|
||||
t.Fatalf("result = %#v, want six common video sources generated", res)
|
||||
}
|
||||
for _, name := range []string{
|
||||
"BluRay.Stream.2026",
|
||||
@@ -102,15 +102,13 @@ func TestGenerateSTRMFromTreeSupportsCommonVideoExtensions(t *testing.T) {
|
||||
"DVD.Feature.2026",
|
||||
"Legacy.Video.2026",
|
||||
"Web.Legacy.2026",
|
||||
"Disc.Image.2026",
|
||||
} {
|
||||
got := readSTRM(t, filepath.Join(outDir, "Movies", name+".strm"))
|
||||
if !strings.Contains(got, "/api/cloud/play/openlist?") {
|
||||
t.Fatalf("%s strm url = %q, want cloud play url", name, got)
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(outDir, "Movies", "Disc.Image.2026.strm")); !os.IsNotExist(err) {
|
||||
t.Fatalf("iso source should stay ignored by tree generator, stat err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateSTRMFromTreeReportsIgnoredFileLikeRows(t *testing.T) {
|
||||
@@ -138,8 +136,8 @@ func TestGenerateSTRMFromTreeReportsIgnoredFileLikeRows(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if res.Generated != 2 || res.Ignored != 6 || len(res.IgnoredItems) != 6 {
|
||||
t.Fatalf("result = %#v, want two generated videos and six ignored sidecars", res)
|
||||
if res.Generated != 3 || res.Ignored != 5 || len(res.IgnoredItems) != 5 {
|
||||
t.Fatalf("result = %#v, want three generated videos and five ignored sidecars", res)
|
||||
}
|
||||
for _, item := range res.IgnoredItems {
|
||||
if item == "Show.Name.2026" || item == "电视剧/Show.Name.2026" {
|
||||
|
||||
@@ -16,7 +16,6 @@ var strmTreeKnownNonVideoExtensions = map[string]struct{}{
|
||||
".bmp": {},
|
||||
".gif": {},
|
||||
".idx": {},
|
||||
".iso": {},
|
||||
".jpeg": {},
|
||||
".jpg": {},
|
||||
".nfo": {},
|
||||
|
||||
Reference in New Issue
Block a user