mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-03 20:26:36 +08:00
fix subscription dedup availability confirmation
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/ShukeBta/MediaStationGo/internal/model"
|
||||
)
|
||||
|
||||
func (o *OrganizerService) reclassifyCloudScannedMedia(ctx context.Context, media model.Media, lib model.Library, mount CloudMountInfo, dryRun bool, res *OrganizeResult) (bool, error) {
|
||||
mediaType := normalizeOrganizeMediaType(lib.Type)
|
||||
metadataMatch := organizeMatchFromMedia(&media)
|
||||
if !mediaHasReliableCategoryMetadata(media) {
|
||||
metadataMatch = o.lookupReclassifyMetadata(ctx, media, lib, mediaType)
|
||||
if metadataMatch == nil {
|
||||
return false, nil
|
||||
}
|
||||
media = mediaWithReclassifyMatch(media, metadataMatch)
|
||||
}
|
||||
if matchType := normalizeOrganizeMediaType(metadataMatchMediaType(metadataMatch)); matchType != "" {
|
||||
mediaType = matchType
|
||||
}
|
||||
category := o.classifyMedia(ctx, &media, mediaType)
|
||||
if category == "" {
|
||||
return false, nil
|
||||
}
|
||||
if impliedType, normalizedCategory := o.mediaTypeForDirectoryCategory(category); impliedType != "" {
|
||||
mediaType = impliedType
|
||||
category = normalizedCategory
|
||||
}
|
||||
if mediaType == "" {
|
||||
mediaType = normalizeOrganizeMediaType(lib.Type)
|
||||
}
|
||||
displayDir := o.cloudReclassifyCategoryDisplayDir(mediaType, category)
|
||||
if displayDir == "" {
|
||||
return false, nil
|
||||
}
|
||||
if normalizeCloudMountDir(mount.Provider, mount.DisplayDir) == normalizeCloudMountDir(mount.Provider, displayDir) {
|
||||
return false, nil
|
||||
}
|
||||
targetLibrary, ok, err := o.ensureCloudReclassifyLibrary(ctx, mount.Provider, displayDir, mediaType, dryRun)
|
||||
if err != nil || !ok {
|
||||
return false, err
|
||||
}
|
||||
if strings.TrimSpace(targetLibrary.ID) != "" && targetLibrary.ID == lib.ID {
|
||||
return false, nil
|
||||
}
|
||||
title := sanitizeFilename(strings.TrimSpace(media.Title))
|
||||
if title == "" {
|
||||
title = "Unknown"
|
||||
}
|
||||
res.Items = append(res.Items, OrganizePreviewItem{
|
||||
Source: media.Path,
|
||||
Target: targetLibrary.Path,
|
||||
Action: "reclassify",
|
||||
Reason: "cloud metadata category library changed",
|
||||
MediaType: mediaType,
|
||||
Category: category,
|
||||
Title: title,
|
||||
})
|
||||
if dryRun {
|
||||
res.Reclassified++
|
||||
return true, nil
|
||||
}
|
||||
updates := map[string]any{
|
||||
"library_id": targetLibrary.ID,
|
||||
"series_id": "",
|
||||
}
|
||||
applyReclassifyMatchUpdates(updates, metadataMatch)
|
||||
if err := o.repo.DB.WithContext(ctx).Model(&model.Media{}).Where("id = ?", media.ID).Updates(updates).Error; err != nil {
|
||||
return false, err
|
||||
}
|
||||
if o.log != nil {
|
||||
o.log.Info("cloud media library reclassified by metadata",
|
||||
zap.String("media", media.ID),
|
||||
zap.String("path", media.Path),
|
||||
zap.String("from_library", lib.ID),
|
||||
zap.String("to_library", targetLibrary.ID),
|
||||
zap.String("category", category),
|
||||
zap.String("media_type", mediaType),
|
||||
zap.String("display_dir", displayDir))
|
||||
}
|
||||
res.Reclassified++
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (o *OrganizerService) cloudReclassifyCategoryDisplayDir(mediaType, category string) string {
|
||||
category = sanitizeFilename(strings.TrimSpace(category))
|
||||
if category == "" {
|
||||
return ""
|
||||
}
|
||||
root := o.mediaTypeRootDirForCategory(mediaType, category)
|
||||
if root == "" {
|
||||
return ""
|
||||
}
|
||||
return strings.Join([]string{root, category}, "/")
|
||||
}
|
||||
|
||||
func (o *OrganizerService) ensureCloudReclassifyLibrary(ctx context.Context, provider, displayDir, mediaType string, dryRun bool) (model.Library, bool, error) {
|
||||
if o == nil || o.repo == nil || o.repo.Library == nil {
|
||||
return model.Library{}, false, nil
|
||||
}
|
||||
provider = strings.TrimSpace(provider)
|
||||
displayDir = normalizeCloudMountDir(provider, displayDir)
|
||||
if provider == "" || displayDir == "" {
|
||||
return model.Library{}, false, nil
|
||||
}
|
||||
if existing := o.findCloudReclassifyLibrary(ctx, provider, displayDir); existing != nil {
|
||||
return *existing, true, nil
|
||||
}
|
||||
path := BuildCloudAutoCategoryLibraryPath(provider, displayDir)
|
||||
if path == "" {
|
||||
return model.Library{}, false, nil
|
||||
}
|
||||
name := cloudMountDirBase(displayDir)
|
||||
if name == "" {
|
||||
name = displayDir
|
||||
}
|
||||
libType := InferCloudMountMediaType(displayDir, name)
|
||||
if normalizeOrganizeMediaType(libType) == "" {
|
||||
libType = organizeLibraryModelType(mediaType)
|
||||
}
|
||||
lib := model.Library{
|
||||
Name: name,
|
||||
Path: path,
|
||||
Type: libType,
|
||||
Enabled: true,
|
||||
}
|
||||
if dryRun {
|
||||
return lib, true, nil
|
||||
}
|
||||
if err := o.repo.Library.Create(ctx, &lib); err != nil {
|
||||
if existing := o.findCloudReclassifyLibrary(ctx, provider, displayDir); existing != nil {
|
||||
return *existing, true, nil
|
||||
}
|
||||
return model.Library{}, false, err
|
||||
}
|
||||
if o.log != nil {
|
||||
o.log.Info("created cloud metadata reclassify library",
|
||||
zap.String("library_id", lib.ID),
|
||||
zap.String("provider", provider),
|
||||
zap.String("display_dir", displayDir),
|
||||
zap.String("type", lib.Type))
|
||||
}
|
||||
return lib, true, nil
|
||||
}
|
||||
|
||||
func (o *OrganizerService) findCloudReclassifyLibrary(ctx context.Context, provider, displayDir string) *model.Library {
|
||||
if o == nil || o.repo == nil || o.repo.Library == nil {
|
||||
return nil
|
||||
}
|
||||
libs, err := o.repo.Library.List(ctx)
|
||||
if err != nil {
|
||||
if o.log != nil {
|
||||
o.log.Warn("list cloud libraries for metadata reclassify failed", zap.Error(err))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
displayDir = normalizeCloudMountDir(provider, displayDir)
|
||||
for _, lib := range libs {
|
||||
if !lib.Enabled {
|
||||
continue
|
||||
}
|
||||
info, ok := ParseCloudLibraryMount(lib.Path)
|
||||
if !ok || info.Provider != provider {
|
||||
continue
|
||||
}
|
||||
if normalizeCloudMountDir(provider, info.DisplayDir) == displayDir {
|
||||
return &lib
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user